Realm và RxJava
Request Api
Trước khi sử dụng Realm, ta có một câu lệnh request API đơn giản:
Thêm Realm vào việc lưu trữ data
Giờ ta sẽ cho thêm Realm vào giữa đoạn lệnh từ Rest Call đến hiển thị lên giao diện. Response trả về sẽ được lưu vào database trước khi nó được hiển thị. Để làm việc này, trước tiên ta phải tạo một WeatherRealm object để quản lý việc lưu trữ dữ liệu.
Các bước cơ bản như sau:
- Request API
- Lấy response trả về lưu vào DB
- Đọc response từ DB
- Hiển thị response.
Từ lần thứ hai request API, đầu tiên ta sẽ hiển thị response cũ trước đó đã được lưu vào database và sau đó nhận lại dữ liệu mới nhất từ API.
Các bước cơ bản như sau:
- Lấy dữ liệu từ DB (Cached data)
- Hiển thị dữ liệu
- Request API
- Lấy response trả về lưu vào DB
- Lấy dữ liệu từ DB
- Hiển thị dữ liệu
Các bước trên đã tương đối ổn rồi, giờ ta sẽ thêm phần xử lý luồng
Để tránh việc bị block UI ta sẽ không ghi data vào DB trên main thread
, ngoài ra, để tránh việc block network call trên IO thread
, ta sẽ xử lý việc này trên Computation thread
Ta sẽ xử lý việc ghi dữ liệu vào DB trên Computation thread
để tránh việc bị block UI khi chạy trên Main Thread
hoặc làm chậm quá trình request API khi chạy trên IO Thread
Coding
Đầu tiên, ta tạo WeatherRealm
extend RealmObject
để xử lý việc đọc, ghi dữ liệu:
public class WeatherRealm extends RealmObject {
@PrimaryKey
private String name;
private Double temp;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getTemp() {
return temp;
}
public void setTemp(Double temp) {
this.temp = temp;
}
}
Lấy dữ liệu từ DB
private Realm realmUI;
protected void onCreate(Bundle savedInstanceState) {
// ...
realmUI = Realm.getDefaultInstance();
// ...
}
private WeatherRealm readFromRealm(String name) {
return findInRealm(realmUI, name);
}
private WeatherRealm findInRealm(Realm realm, String name) {
return realm.where(WeatherRealm.class).equalTo("name", name).findFirst();
}
@Override
protected void onDestroy() {
super.onDestroy();
realmUI.close();
}
Ta tạo một instance của Realm để xử lý việc đọc dữ liệu trên UI Thread, biến này được gọi là realmUI, đừng quên close nó trong hàm onDestroy() để tránh việc leak bộ nhớ.Hàm findInRealm chứa câu lệnh query tìm các object trong database theo tên thành phố.
Lưu trữ dữ liệu vào DB
Tạo Observable
Giờ đã là lúc để kết hợp lại tất cả mọi thứ với nhau:
Kết hợp với dữ liệu đã được cached
Chạy thử
Sau khi chạy ta sẽ thấy hàm onNext được gọi ra 2 lần, một lần là từ dữ liệu cache và một lần là dữ liệu từ API trả về. Tất nhiên lần gọi đầu tiên gần như ngay lập tức vì dữ liệu đã được lưu sẵn dưới DB, lần gọi thứ 2 sẽ chậm hơn sau 1 giây.