Day 7 - Android AsyncHttp
สวัสดีครับ บทความนี้เป็นบทความที่ 7 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days
สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ
- Day 1 : AndroidStaggered Grid
- Day 2 : Paralloid
- Day 3 : Retrofit
- Day 4 : SwipeRefreshLayout
- Day 5 : Android GraphView
- Day 6 : Holo Color Picker
- Day 7 : Android Async Http
- Day 8 : Crashlytics
- Day 9 : Butter Knife
- Day 10 : Android Annotations
- Day 11 : DateTimePicker
- Day 12 : Circular Progress Button
- Day 13 : ViewPager
- Day 14 : ViewPagerIndicator
- Day 15 : FadingActionBar
- Day 16 : AutofitTextView
- Day 17 : SwipeListView
- Day 18 : ShowcaseView
- Day 19 : GreenDAO
- Day 20 : AndroidViewAnimation
- Day 21 : ActiveAndroid
- Day 22 : Twitter4J
- Day 23 : ListViewAnimations
- Day 24 : AndEngine
- Day 25 : EazeGraph
- Day 26 : Cardslib
- Day 27 : AdapterKit
- Day 28 : WeatherLib
- Day 29 : FlatUI
- Day 30 : Android Firebase
สำหรับวันนี้ขอนำเสนอเรื่อง 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 ในกรอบมาใส่
ทดสอบรันดู ก็ได้ดังรูป มีผลลัพธ์ตอบกลับมาแล้ว ผลลัพธ์เดียวกัน ถ้าเข้าหน้าเว็บด้วย http://web-60388f0d-d0d6-4b9a-bcf8-61d0507ea2b9.runnable.com/api/players (ส่วนนี้มันถูก gen ทุกครั้งที่ run อาจจะได้ url ไม่เหมือนกันนะครับ)
จากหน้าเว็บ
ข้อมูลด้านบนไม่อัพเดทนะครับ ปัจจุบัน ซัวเรส ย้ายไปบาร์เซโลน่าแล้ว ฮ่าๆ
ต่อมา ผมเห็นแล้วว่าส่งค่ามาเป็น 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 ผลลัพธ์เป็นแบบนี้
อันนี้ก็เป็นตัวอย่างแบบ 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 แค่นี้ก่อนครับ ขอบคุณครับ
- Authors
- Name
- Chai Phonbopit
- Website
- @Phonbopit