RxJava 2 và Retrofit trong ứng dụng Android
Bài đăng này đã không được cập nhật trong 7 năm
- RxJava là 1 Reactive dựa trên Java framework. Nó giúp bạn thực hiện các tác vụ đồng bộ hoặc không đồng bộ trong chương trình. Trong bài này mình sẽ hướng dẫn các bạn sử dụng RxJava kết hợp với Retrofit để thức hiện lấy dữ liệu từ API.
1. Bắt đầu
- Khởi tao Project: trong ví dụ này mình sẽ khởi tạo 1 ứng dụng với package com.demo.retrofitrxjava, Activity là MainActivity và layout là activity_main.
- Thêm Dependencies và enabling Jack compiler: Trong file app’s build.gradle.
jackOptions {
enabled true
}
Chúng ta cần cài đặt Java version 8 để có thể sử dụng cách viết Lambda trong code.
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
Thêm các dependencies cần thiết.
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
ở trên mình đã thêm các thứ viện r RxJava, Retrofit, Card View và Recycler View.
- Thêm Permissions vào Manifest
<uses-permission android:name="android.permission.INTERNET"/>
2. Xây dụng các layout, Model và các Interface cần thiết cho ứng dụng
Xây dựng layout
Trong layout activity_main.xml chúng ta sẽ sử dụng một RecyclerView bao ngoài là 1 ViewGroup là Relative Layout.
// 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"
tools:context="com.demo.retrofitrxjava.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Tiếp tới là 1 layout cho các item của RecylerView với các TextView để hiển thị Android version name, version number and API level.
// recycler_row.xml
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_api_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
Xây dựng Model
Như layout recycler_row.xml
ở trên mình xây dựng, thì mình cần 1 Model với 3 trường để chứa các dữ liệu Android version name, version number and API level
// package com.demo.retrofitrxjava.model;
public class Android {
private String ver;
private String name;
private String api;
public String getVer() {
return ver;
}
public String getName() {
return name;
}
public String getApi() {
return api;
}
}
Tạo Retrofit Interface
Vì ở đây chúng ta sử dụng kết hợp giữa RxJava và Retrofit nên đối tượng trả về của hàm được định nghĩa này cần là 1 Observable
.
// package com.demo.retrofitrxjava.network;
public interface RequestInterface {
@GET("android/jsonarray/")
Observable<List<Android>> register();
}
Tạo Adapter cho RecyclerView
Tạo file DataAdapter.java
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<Android> mAndroidList;
public DataAdapter(ArrayList<Android> androidList) {
mAndroidList = androidList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTvName.setText(mAndroidList.get(position).getName());
holder.mTvVersion.setText(mAndroidList.get(position).getVer());
holder.mTvApi.setText(mAndroidList.get(position).getApi());
}
@Override
public int getItemCount() {
return mAndroidList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView mTvName,mTvVersion,mTvApi;
public ViewHolder(View view) {
super(view);
mTvName = (TextView)view.findViewById(R.id.tv_name);
mTvVersion = (TextView)view.findViewById(R.id.tv_version);
mTvApi = (TextView)view.findViewById(R.id.tv_api_level);
}
}
}
DataAdapter
có nhiệm vụ chuyển đổi dữ liệu đầu vào là 1 List<Android> androidList
lấy từ API và hiển thị lên màn hình dưới dạng danh sách các phần tử riêng biệt .
3. Khởi tạo Activity
Ở đây mình sẽ khởi tạo 1 đối trượng CompositeDisposable
để thêm tất cả các .subscribe()
và đó và clear
nó khi Activity onDestroy(). Trong RxJava 1 thì chúng ta khởi tao đối tượng CompositeSubscription
nhưng trong phiên bản từ 2.0 trở đi Rxjava đã loại bỏ đối tượng này.
Khởi tạo RecyclerView
Khởi tạo RecyclerView
private void initRecyclerView() {
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(layoutManager);
}
Lấy dữ liệu từ server
private void loadJSON() {
RequestInterface requestInterface = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(RequestInterface.class);
Disposable disposable = requestInterface.register()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::handleResponse, this::handleError);
mCompositeDisposable.add(disposable);
}
ở đây chắc các bạn thấy cách viết mới mẻ này subscribe(this::handleResponse,this::handleError))
. Thức chất đây là cách viết ngắn gọn của Java 8 Lambda
. Cách viết đầy đủ sẽ là
subscribe(response -> handleResponse(response), error -> handleError(error))
Khi chung ta thêm Disposable
vào CompositeDisposable
thông qua phương thức mCompositeDisposable.add(disposable);
và mình sẽ gọi hàm mCompositeDisposable.clear()
khi Activity gọi vào hàm onStop()
hay onDestroy()
sẽ tránh được trường hợp bị mất Context
khi Activity bị kill.
Hàm xử lý dữ liệu trả về
private void handleResponse(List<Android> androidList) {
mAndroidArrayList = new ArrayList<>(androidList);
mAdapter = new DataAdapter(mAndroidArrayList);
mRecyclerView.setAdapter(mAdapter);
}
private void handleError(Throwable error) {
Toast.makeText(this, "Error " + error.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
private void handleSuccess() {
Toast.makeText(this, "Get data success! ", Toast.LENGTH_SHORT).show();
}
Ở đây hàm handleResponse()
sẽ nhận dữ liệu từ hàm onNext()
của subscribe
và hiển thị dữ liệu lên RecyclerView
.
Hai hàm handleError
và handleSuccess
sẽ nhận 2 sự kiện onError()
và onComplete()
từ subscribe
để bắt các sự kiện khi sảy ra lỗi hoặc là kết thúc.
Ở trên mình đã giới thiệu cơ bản với các bạn về cách kết hợp giữa RxJava 2
và Retrofit
trong ứng dụng Android để lấy dữ liệu từ API.
Thông qua bài viết trên các bạn có thể thấy sự khác nhau cơ bản giữa RxJava 2
và RxJava
là sự khác nhau ở cách .subscribe()
và cách quản lý sự kiện thông qua đối tượng CompositeDisposable
trong RxJava
.
Link source code tham khảo: https://github.com/huyquyet/DemoRxJava2Retrofit
All rights reserved