使用RxJava和改造实施机房 [英] Implement Room with RxJava and Retrofit

查看:70
本文介绍了使用RxJava和改造实施机房的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将Room与RxJava和Retrofit一起使用,然后建议您使用组件弓(在这种情况下,该项目已成50%的机会,并且仅需要继续进行弓清理)是不可能的.

I am trying to use Room with RxJava and Retrofit, Before You recommend use a component arch (In this opportunity is not possible, the project is in and 50% and Just need to continue with the arch clean).

所以问题是这个.我有一个返回 POJO 的Web服务.像这样:

So the problem is this. I have a web service that returns a POJO. Something like this:

{
 "success":"true",
 "message":"message",
 "data":{[
   "id":"id",
   "name":"name",
   "lname":"lname",
 ]} 
}

POJO更为复杂,但是对于这个例子来说是可以的.我需要这样做,因为我的视图进行查询以从room调用数据,但是如果我的db中没有数据,请调用我的Web服务,我的web服务的响应将转换为实体并保存在我的db(room)中并在返回后保存我查看的数据列表.

POJO is more complex but for the example is ok with this. I need to do that since my view make query to invoke data from room, but if there is not data in my db call my web services,the reponse of my web services transform to entity and save in my db (room) and after return a list of data to my view.

我正在使用整洁的拱门.我对此表示感谢.再次不尝试使用

I am using clean arch. I appreciate anyhelp with this. Again not trying to use

数据布局

  • 数据库
  • 网络
  • 存储库

  • 交互器
  • 回调

演示文稿

  • 演示者
  • 视图

POJO API响应

POJO API response

{
 "success":"true",
 "message":"message",
 "data":{[
   "id":"id",
   "name":"name",
   "address":"address",
   "phone":"phone",
 ]} 
}

我的数据库实体

My db entity

@Entity(tableName = "clients")
    public class clients {

    String id;
    String name;
    String address;
    String phone;
    String status;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

我的房间房间

My dao for room

@Dao
public interface ClientsDao {

     @Insert(onConflict = OnConflictStrategy.REPLACE)
     void saveAll(List<Clients> clients);

     @Query("SELECT * FROM Clients")
     Flowable<List<Clients>> listClients();

}

RxJava帮助类

RxJava help class

public class RxHelper {
private static final String TAG = RxHelper.class.getName();

@NonNull
public static <T>Observable<T> getObserbable(@NonNull final Call<T> reponse){

    return Observable.create(new ObservableOnSubscribe<T>() {
        @Override
        public void subscribe(final ObservableEmitter<T> emitter) throws Exception {

            reponse.enqueue(new Callback<T>() {
                @Override
                public void onResponse(Call<T> call, Response<T> response) {

                    if (!emitter.isDisposed()) {
                        emitter.onNext(response.body());
                    }
                }

                @Override
                public void onFailure(Call<T> call, Throwable t) {
                    if (!emitter.isDisposed()) {
                        emitter.onError(t);
                    }
                }
            });

        }
    });

}
}

我的客户RepoFactory

My ClientsRepoFactory

public Observable<ResponseClients> getApiClients(){
        String token = preferences.getValue(SDConstants.token);
        return RxHelper.getObserbable(apiNetwork.getClients(token));
}

我的客户回购

My ClientsRepo

@Override
public Observable<ResponseClients> listClients() {
    return factory.listClients();
}

推荐答案

我不处理空间,但是熟悉rxjava时,您可以像这样设计存储库

i dont work with room but familiar with rxjava you can design your repository like that

您的房间界面

@Query("SELECT * FROM Users WHERE id = :userId")
Single<User> getUserById(String userId);

使用时:
也许:如果数据库中没有用户,并且查询不返回任何行,则可能会完成.

when use :
Maybe When there is no user in the database and the query returns no rows, Maybe will complete.

Flowable 每次更新用户数据时,Flowable对象都会自动发出,从而允许您根据最新数据更新UI

Flowable Every time the user data is updated, the Flowable object will emit automatically, allowing you to update the UI based on the latest dat

:当数据库中没有用户并且查询不返回任何行时,Single将触发onError(EmptyResultSetException.class)

Single When there is no user in the database and the query returns no rows, Single will trigger onError(EmptyResultSetException.class)

通过链接

要实现如果db call Web服务中没有数据",请像这样创建存储库方法

to achieve " if there is not data in db call web services " create your repository methode like that

public Single<User> getUserById(String userId){
 return  db.getUserById(userId)
              /// if there is no user in the database get data from api
             .onErrorResumeNext(api.getUserById(userId)
              .subscribeOn(Schedulers.io())
              //check your request
              .filter(statusPojo::getStatus)
               // save data to room
              .switchMap(data -> {
              //sava data to db
              return Observable.just(data)
              })
           );

}

最终从交互器调用存储库方法,将其传递给交互器,然后再传递给演示文稿布局

finally call repository method from interactor to passed obsrevable to interactor then to presentation layout

更多细节:您可以将Api和DB注入到您的存储库

more detail : you can inject Api and DB to your repository

update_Answer 用于反应式数据库 如果您想获取UI的最新更新,请执行以下操作:

update_Answer for reactive db if you want get last update on UI just do it :

您的房间界面:

@Query("SELECT * FROM Users WHERE id = :userId")
Flowable<User> getUserById(String userId);

存储库:

   @Override
public Flowable<User> getUser(int id) {
    getUserFromNet(id);
         //first emit cache data in db and after request complete   emit last update from net 
        return db.getUserById(id);

 }


 private Flowable<User> getUserFromNet(int id){
      api.getUserById(userId)
          .subscribeOn(Schedulers.io())
          .observeOn(Schedulers.io())
          //check your request
          .filter(statusPojo::getStatus)
           // save data to room
          .subscribe(new DisposableObserver<User>() {
                @Override
                public void onNext(User user) {
                     // save data to room
                }

                @Override
                public void onError(Throwable e) {
                    Timber.e(e);
                }

                @Override
                public void onComplete() {


                }
            });
}

update_Answer2 用于响应式数据库,以及如果数据库调用网络服务中没有数据" 根据此问题最好使用返回Flowable <List<T>>

update_Answer2 for reactive db and " if there is not data in db call web services " according this issue is better use return a Flowable <List<T>>

并检查列表大小,而不是Flowable<T>白色swichIfEmpity,因为如果数据库Flowable<T>中没有任何用户,请不要调用onNext()并且不发出FlowableEmpity();

and check list size instead of Flowable<T> white swichIfEmpity because if don't any user in db Flowable<T> do'nt call onNext() and don't emite FlowableEmpity();

private Flowable<List<User>>  getUser(int id){
       return db.getUserById(id).
         /// if there is no user in the database get data from 
           .flatMp(userList-> 
           if(userList.size==0)
          api.getUserById(userId)
          .subscribeOn(Schedulers.io())
          //check your request
          .filter(statusPojo::getStatus)
           // save data to room
          .subscribe(new DisposableObserver<User>() {
                @Override
                public void onNext(User user) {
                     // save data to room
                }

                @Override
                public void onError(Throwable e) {
                    Timber.e(e);
                }

                @Override
                public void onComplete() {


                }
            });
                return Flowable.just(data)
                );
}

Kotlin方式,具有翻新,分页(pagingRX androidx)和空间:

Kotlin way with retrofit , paging (pagingRX androidx) and room :

房间道:

@Dao
abstract class UserDao   {

@Query("SELECT * FROM users ")
abstract fun findAll(): DataSource.Factory<Int, User>
}

存储库:

private fun getFromDB(pageSize:Int): Flowable<PagedList<User>> {
    return RxPagedListBuilder(userDao.findAll(), pageSize)
        .buildFlowable(BackpressureStrategy.LATEST)
}


private fun getApi(page: Int,pageSize: Int): Disposable {
    return api.getUserList("token", page = page,perPage = pageSize)
        .subscribeOn(Schedulers.io())
        .observeOn(Schedulers.io())
        .subscribe { t1: List<User>?, t2: Throwable? ->
            t1?.let {
                if (it.isNotEmpty())
                    userDao.insert(it)
            }
        }
}

override fun  findAll(page: Int ,pageSize:Int ): 
Flowable<PagedList<User>> {
    return getFromDB(pageSize).doOnSubscribe { getApi(page,pageSize) }
}

这篇关于使用RxJava和改造实施机房的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆