Khóa học lập trình Android cơ bản

Serial tutorial hướng dẫn lập trình Android cơ bản

JSON và web API trong lập trình Android cơ bản JSON và web API trong lập trình Android cơ bản JSON và web API trong lập trình Android cơ bản JSON và web API trong lập trình Android cơ bản JSON và web API trong lập trình Android cơ bản 0/5 (68 reviews)

JSON và web API trong lập trình Android cơ bản

Đã đăng 2016-10-17 09:28:34 bởi HowKteam
2 bình luận 17447 lượt xem
JSON và web API trong lập trình Android cơ bản 0 /5 stars (1 reviews)
 

Dẫn nhập

Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về CƠ CHẾ XỬ LÝ BẤT ĐỒNG BỘ TRONG ANDROID và cách sử dụng AsyncTask để dễ dàng thao tác xử lý bất đồng bộ.

Tuy nhiên trong quá trình làm việc, các thao tác xử lý bất đồng bộ thường là các thao tác với mạng. Và mỗi lần phải sử dụng AsyncTask để làm như vậy thì quả là dài.

Bài hôm nay chúng ta sẽ sử dụng một thư viện hỗ trợ mạng cực mạnh, cũng như một bộ xử lý thông tin dạng JSON mà các Web API hay sử dụng rất phổ biến.


Nội dung

Để đọc hiểu bài này tốt nhất các bạn nên có kiến thức cơ bản về các phần:

Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:

  • Cài đặt thư viện OkHttp và Moshi.
  • Sử dụng 2 thư viện trên để lấy dữ liệu đổ vào ứng dụng.

Tạo project mới

Như thường lệ, chúng ta sẽ tạo một project mới với tên là JSONExample

750

Và chọn minSdk là 13:


Cài đặt OkHttp và Moshi

Cài đặt thư viện OkHttp Moshi vào ứng dụng thật ra rất đơn giản. Do Android Studio đã tích hợp Gradle làm build system và chúng ta có thể lấy bất cứ thư viện nào lưu trên jCenter Maven Central (2 website chứa thư viện / dependencies cho Java lớn nhất hiện nay).

Bước 1: Mở file app/build.gradle . Các bạn nhìn ở cột trái sẽ thấy 2 file build.gradle, nhớ chọn cái (module: app) nhé:

Chúng ta thêm 2 dòng sau vào file build.gradle như thế này:

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.howkteam.jsonexample"
        minSdkVersion 13
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'

    compile 'com.android.support:recyclerview-v7:24.2.1'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.squareup.moshi:moshi:1.2.0'
    compile 'com.squareup.picasso:picasso:2.5.2'
}

(Picasso là thư viện giúp hiển thị hình ảnh thuận tiện hơn, sẽ được sử dụng trong ví dụ).

Bước 2: Nhấn vào chữ Sync Now hoặc nút Sync như hình khoanh đỏ. Nhấn 1 lần thôi nhé, để Android Studio tự đồng bộ và download dependency về.


Nhắc lại về Model và JSON

Khi các bạn làm về Android tức là các bạn đã biết về Java cơ bản, mà đã là Java cơ bản thì chắc chắn không xa lạ gì khái niệm Model.

Model là một lớp mẫu cho đối tượng nào đó. Ví dụ model Person thì sẽ có 2 trường là String name và int age chẳng hạn.

Thứ 2 là về định dạng dữ liệu JSON. Ở đây chúng ta sẽ lấy dữ liệu từ trang này:

https://api.github.com/users

Đây là API public của Github, trả về một danh sách các người dùng Github. Và cái chúng ta muốn là đưa danh sách này hiển thị thành RecyclerView trong Android cho dễ xem.

Để cho đơn giản thì chúng ta chỉ lấy 3 trường trong json là login, id avatar_url.

Bước 1: Đầu tiên chúng ta tạo một file .java mới để làm model, lấy tên là User.java:

 
package com.howkteam.jsonexample;

public class User {
    public String login;
    public int id;
    public String avatar_url;
}

Đó, chỉ cần vậy thôi.

Bước 2: Tạo layout cho item của RecyclerView mà chúng ta muốn cho hiển thị:

Item_user.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="8dp">

    <ImageView
        android:id="@+id/iv_avatar"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"/>

    <TextView
        android:id="@+id/tv_login_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_toRightOf="@id/iv_avatar"/>

    <TextView
        android:id="@+id/tv_id"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_login_name"
        android:layout_toRightOf="@id/iv_avatar"/>

</RelativeLayout>

Bước 3: Tạo Adapter cho RecyclerView. Để biết cách tạo, các bạn xem lại bài RECYCLERVIEW & VIEWHOLDER:

UserAdapter.java

package com.howkteam.jsonexample;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.List;

public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserItemViewHolder> {
    private List<User> users;
    private Context context;

    public UserAdapter(List<User> users, Context c) {
        this.users = users;
        this.context = c;
    }

    @Override
    public int getItemCount() {
        return users.size();
    }

    @Override
    public UserItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_user, parent, false);

        return new UserItemViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(UserItemViewHolder holder, int position) {
        User u = users.get(position);
        Picasso.with(context)
                .load(u.avatar_url)
                .into(holder.ivAvatar);
        holder.tvLoginName.setText(u.login);
        holder.tvId.setText(String.valueOf(u.id));
    }

    public static class UserItemViewHolder extends RecyclerView.ViewHolder {
        public TextView tvLoginName;
        public TextView tvId;
        public ImageView ivAvatar;

        public UserItemViewHolder(View itemView) {
            super(itemView);
            tvLoginName = (TextView) itemView.findViewById(R.id.tv_login_name);
            tvId = (TextView) itemView.findViewById(R.id.tv_id);
            ivAvatar = (ImageView) itemView.findViewById(R.id.iv_avatar);
        }
    }
}

Bước 4: Cuối cùng, chỉnh sửa lại file activity_main.xml, MainActivity.java và thêm permission INTERNET cho AndroidManifest:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.howkteam.jsonexample.MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_users"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

MainActivity.java

package com.howkteam.jsonexample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

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

        // Khởi tạo RecyclerView.
        final RecyclerView rvUsers = (RecyclerView) findViewById(R.id.rv_users);
        rvUsers.setLayoutManager(new LinearLayoutManager(this));

        // Khởi tạo OkHttpClient để lấy dữ liệu.
        OkHttpClient client = new OkHttpClient();

        // Khởi tạo Moshi adapter để biến đổi json sang model java (ở đây là User)
        Moshi moshi = new Moshi.Builder().build();
        Type usersType = Types.newParameterizedType(List.class, User.class);
        final JsonAdapter<List<User>> jsonAdapter = moshi.adapter(usersType);

        // Tạo request lên server.
        Request request = new Request.Builder()
                .url("https://api.github.com/users")
                .build();

        // Thực thi request.
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("Error", "Network Error");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                
                // Lấy thông tin JSON trả về. Bạn có thể log lại biến json này để xem nó như thế nào.
                String json = response.body().string();
                final List<User> users = jsonAdapter.fromJson(json);
                
                // Cho hiển thị lên RecyclerView.
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        rvUsers.setAdapter(new UserAdapter(users, MainActivity.this));
                    }
                });
            }
        });
    }
}

 

Và trong AndroidManifest:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.howkteam.jsonexample">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

 

Và chúng ta sẽ được kết quả:


Vậy lợi ích ở đây là gì?

Về bản chất, việc sử dụng 2 thư viện OkHttp và Moshi không khác gì so với dùng AyncTask kèm JSONObject – 2 thư viện có sẵn của Android, nhưng…

  • Android không cho phép thao tác mạng trên UI Thread, do đó phải thực hiện theo kiểu bất đồng bộ. OkHttp hỗ trợ rất tốt việc này, mà code lại ngắn hơn do không phải viết class AsyncTask.
  • Moshi giúp chúng ta chuyển đổi thẳng từ tên các trường trong Model ra JSON.
  • Kết hợp cả 2 thư viện này với Picasso để hỗ trợ load ảnh, chúng ta đã viết được một chương trình con rất nhanh.

Kết luận

Qua bài này chúng ta đã nắm được cách sử dụng OkHttp theo kiểu bất đồng bộ thay cho AsyncTask, kết hợp với Moshi để xử lý dữ liệu JSON đổ vào danh sách trong Android.

Bài sau chúng ta sẽ tìm hiểu về PERMISSION TRONG ANDROID, vấn đề tưởng chừng nhỏ nhưng cũng có phần phức tạp.

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.


Tài liệu 

Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học JSON và web API trong lập trình Android cơ bản dưới dạng file PDF trong link bên dưới.

Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com

Đừng quên like hoặc +1 Google để ủng hộ Kteam và tác giả nhé! 


Thảo luận

Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần BÌNH LUẬN bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng. 

 

Chia sẻ:
Thảo luận Hỏi và đáp Báo lỗi bài viết
Hủy bỏ   hoặc  
JSON và web API trong lập trình Android cơ bản
khacduongcntt 2018-05-21 11:24:18

Lỗi này là lỗi gì vậy ad

 Process: com.example.m4800.tapbibuzz, PID: 974
 com.squareup.moshi.JsonDataException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at path $
 

0 bình chọn
Reply
JSON và web API trong lập trình Android cơ bản
Trúc 2017-01-09 12:34:42
Làm s để tạo được https://api.github.com/users vậy ad?
1 bình chọn
Reply
Hủy bỏ   hoặc  
Hủy bỏ   hoặc  

Chiến dịch

Kteam - Howkteam Free Education