Day 7 - Android AsyncHttp

Published on
Android
2014/07/day-7-learn-android-async-http
Discord

สวัสดีครับ บทความนี้เป็นบทความที่ 7 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days

สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ

สำหรับวันนี้ขอนำเสนอเรื่อง Android Async Http ครับ สำหรับใครที่เคยติดตามอ่านบล็อกผมเก่าๆ อาจจะพบว่าผมเคยนำมาใช้แล้ว แต่ว่ายังไม่เคยพูดถึง รายละเอียดเท่าไหร่ วันนี้เลยถือโอกาส Overview มาให้ละกันครับ

Android Async Http คืออะไร?

Android Async Http เป็น Asynchronous Callback Http เพื่อแก้ไขปัญหา OnMainThreadException เนื่องจาก Library ตัวนี้ มันทำงานนอก Main UI Thread ครับ การใช้งานก็ง่าย มี Callback กลับมา มี response code กลับมา ว่า error หรือ success สำหรับใครที่ไม่อยากใช้ AsyncTask เวลาคอนเนค Http ก็มาลองใช้ตัวนี้ได้

Features

  • Asynchronous Http Requrest และ Callback
  • การทำงาน ทำงานนอก UI Thread ทำให้ไม่มีปัญหา OnMainThreadException
  • รองรับ GET/POST ผ่าน RequestParam
  • รองรับ Multipart File
  • รองรับ JSON
  • อื่นๆ อีกเพียบ อ่านได้จาก Documentation

Installaton

ในส่วนขั้นตอนการติดตั้ง หากใครใช้แบบ jar ก็โหลดไฟล์ได้ที่นี่ andriod-async-http-1.4.5.jar แล้วก็อปไปไว้ที่โฟลเดอร์ libs/ ในโปรเจ็ค จากนั้นเปิดไฟล์ build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

แล้ว Sync Project

หรือหากใครต้องการใช้มันโหลดมาจาก Maven Central เลย ก็แค่เพิ่มนี้ลงไปใน build.gradle

dependencies {
    compile 'com.loopj.android:android-async-http:1.4.5'
}

กด Sync Project

หากใครมี error ว่าหาไฟล์ library จาก mavenCentral ไม่เจอ สาเหตุก็เพราะว่า Android Studio เปลี่ยนไปใช้ jCenter() สำหรับ search หา repository แทน mavenCentral() แล้ว ฉะนั้นก็ต้องเพิ่ม ส่วนนี้ลงไปที่ไฟล์ build.gradle ของ Root Project คนละไฟล์กับด้านบนนะ!

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ...
}

allprojects {
    repositories {
        jcenter()
        maven {
            url 'http://repo1.maven.org/maven2/'
        }
    }
}

Getting Started

สำหรับการใช้งานเจ้า Android Async Http นั้น ใน Document มีตัวอย่างให้ดูแล้วครับ แถมมี Sample Code ให้ดูอีก สำหรับใครที่ยังไม่มีพื้นฐาน แนะนำให้อ่าน Document และ Sample Code ประกอบนะครับ

GET

การ get นั้นทำได้ง่ายมากๆ ด้วยโค๊ดนี้

String URL = "https://devahoy.com";
AsyncHttpClient client = new AsyncHttpClient();
client.get(URL, new AsyncHttpResponseHandler() {
    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {

    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {

    }
});

มาลองทำโปรเจ็คเล่นๆดูครับ ผมใช้ 2 ไฟล์คือ AndroidAsyncActivity.java และไฟล์เลเอาท์ชื่อ activity_async.xml เอาไว้สำหรบแสดงผลลัพธ์กลับมาครับ ถ้าใช้ Toast มันจะมองไม่ทัน

เริ่มแรก ทีไฟล์เลเอาท์เป็นแบบนี้

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:padding="16dp"
              android:orientation="vertical">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:singleLine="false"/>

    </ScrollView>


</LinearLayout>

คือเอาไว้แสดงผลลัพธ์เฉยๆ ไม่มีอะไรมาก

ส่วนที่ไฟล์จาวา ผมก็ใส่ดังนี้

package com.devahoy.learn30androidlibraries.day7;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;

import com.devahoy.learn30androidlibraries.R;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import org.apache.http.Header;

public class AndroidAsyncActivity extends ActionBarActivity {

    private TextView mText;
    private final String URL =
            "http://web-60388f0d-d0d6-4b9a-bcf8-61d0507ea2b9.runnable.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.day7_activity_async);

        mText = (TextView) findViewById(R.id.text);

        AsyncHttpClient client = new AsyncHttpClient();
        client.get(URL + "/api/players", new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                if (statusCode == 200) {
                    mText.setText(new String(responseBody));
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {

            }
        });

    }
}

ด้านบนในส่วน URL ต้องไปเปลี่ยนค่าเอาเองนะครับ ตัวอย่าง ผมลองทำ REST API เอาไว้แบบ sample นะครับ ตอนนั้นทำไว้เล่นๆ เอามาใช้ซะเลย โดยรันไว้ที่เว็บ Runnable เผื่อส่งค่า JSON กลับมา ดูรายละเอียดได้จากนี่้ RESTFul API with Node.js & Express 4 ให้กด Run จากนั้นค่อยเอา URL ในกรอบมาใส่

Copy Url

ทดสอบรันดู ก็ได้ดังรูป มีผลลัพธ์ตอบกลับมาแล้ว ผลลัพธ์เดียวกัน ถ้าเข้าหน้าเว็บด้วย http://web-60388f0d-d0d6-4b9a-bcf8-61d0507ea2b9.runnable.com/api/players (ส่วนนี้มันถูก gen ทุกครั้งที่ run อาจจะได้ url ไม่เหมือนกันนะครับ)

OnMobile

จากหน้าเว็บ

OnWeb

ข้อมูลด้านบนไม่อัพเดทนะครับ ปัจจุบัน ซัวเรส ย้ายไปบาร์เซโลน่าแล้ว ฮ่าๆ

ต่อมา ผมเห็นแล้วว่าส่งค่ามาเป็น JSON ฉะนั้นก็จะแมพ JSON เข้ากับ Model ที่กำลังสร้างเลย แบบนี้

ไฟล์ Player.java

package com.devahoy.learn30androidlibraries.day7;

public class Player {

    private String id;
    private String name;
    private String club;
    private String national;
    private int age;

    // GETTER and SETTER
    // ...

ไฟล์ Players.java

package com.devahoy.learn30androidlibraries.day7;

import java.util.List;

public class Players {
    private List<Player> players;

    public List<Player> getPlayers() {
        return players;
    }

    public void setPlayers(List<Player> players) {
        this.players = players;
    }
}

ผมใช้ Gson เข้ามาช่วยนิดนึง อ่านข้อมูล JSON ด้วย Gson บน Android ได้แบบนี้

package com.devahoy.learn30androidlibraries.day7;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;

import com.devahoy.learn30androidlibraries.R;
import com.google.gson.Gson;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;

import org.apache.http.Header;

public class AndroidAsyncActivity extends ActionBarActivity {

    private TextView mText;
    private final String URL =
            "http://web-60388f0d-d0d6-4b9a-bcf8-61d0507ea2b9.runnable.com";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.day7_activity_async);

        mText = (TextView) findViewById(R.id.text);

        final Gson gson = new Gson();

        AsyncHttpClient client = new AsyncHttpClient();
        client.get(URL  + "/api/players", new AsyncHttpResponseHandler() {
            @Override
            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                if (statusCode == 200) {
                    // mText.setText(new String(responseBody));
                    StringBuilder result = new StringBuilder();

                    Players players = gson.fromJson(new String(responseBody),
                            Players.class);

                    for (Player player : players.getPlayers()) {
                        result.append("Name: " + player.getName() + "\n");
                        result.append("Age : " + player.getAge() + "\n");
                        result.append("Club : " + player.getClub() + "\n");
                        result.append("National : " + player.getNational() + "\n");
                        result.append("================\n");
                    }

                    mText.setText(result);
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {

            }
        });

    }
}

จากตัวอย่างด้านบน ก็ทำการแมพ JSON กับคลาสที่ผมสร้างขึ้น จากนั้น ก็เอามาแสดงใน TextView ผลลัพธ์เป็นแบบนี้

Result

อันนี้ก็เป็นตัวอย่างแบบ Basic นะครับ จริงๆจะทำเป็น ListView แล้วเวลากดแต่ละ Player ก็ไปหน้ารายละเอียด แต่ว่า เว้นไว้ละกันครับ ไม่มีเวลาทำ + ขี้เกียจ :D

POST

ส่วนการ POST ก็ทำได้ไม่ยากเลย แค่ใช้ RequestParams แล้วก็เปลี่ยนเป็นเมธอด post ซะ แบบนี้

RequestParams params = new RequestParams();
params.put("name", "Marco Reus");
params.put("national", "Germany");

AsyncHttpClient client = new AsyncHttpClient();
client.post(URL, params, new AsyncHttpResponseHandler() {
    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
        // check statusCode and get responsebody
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
        // throw err.
    }
});

แล้วก็ยังมีอีกหลายๆอย่างครับ ไม่ว่าจะเป็นการอัพโหลดไฟล์ การดาวน์โหลดไฟล์ สามารถศึกษาเพิ่มเติมได้จากเว็บต้นฉบับเลยครับ สำหรับบทความนี้ก็ขอแนะนำ วิธีการใ้ช้งานเบื้องต้น ในแบบฉบับ Overview แค่นี้ก่อนครับ ขอบคุณครับ

Buy Me A Coffee
Authors
Discord