RxJava 和 Realm 请求使应用程序跳帧

Posted

技术标签:

【中文标题】RxJava 和 Realm 请求使应用程序跳帧【英文标题】:RxJava and Realm request make app skip frame 【发布时间】:2020-06-21 09:30:28 【问题描述】:

我在一个 android 项目中使用 RxJava 和 Realm 数据库。但有时按下按钮没有响应,您必须多次执行此操作才能使其在某个时间工作,并且 android 日志显示 xxx 帧已跳过。我知道这与滥用 UI 线程有关。这是我的一些要求,有人可以告诉我他们有什么问题吗? Realm 希望我在使用响应的同一线程上执行 IO 请求(虽然不太确定)。

public Flowable<List<ClothingItem>> getClothingItemsLocal() 
    return Flowable.just(dbProvider.getClothingItems(mSortType));


public Flowable<List<ClothingItem>> getClothingItemsRemote() 
    return clothingService.getAll("Bearer " + preferencesManager.getToken())
            .map(response -> response.items)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSuccess(clothingItems -> 
                dbProvider.clearClothingItems();
                dbProvider.saveOrUpdateClothingItems(clothingItems);
            )
            .toFlowable()
            .map(remoteItems -> dbProvider.getClothingItems(mSortType));


public Flowable<ClothingItem> getClothingItem(@NonNull final String id) 
    return getClothingItemRemote(id)
            .startWith(dbProvider.getClothingItem(id))
            .onErrorReturn(throwable -> dbProvider.getClothingItem(id));

getAll 方法与改造。

@GET(BuildConfig.BASE_API_PATH + "clothing_items")
Single<GetClothingItemsResponseModel> getAll(@Header("Authorization") String token);

领域提供者方法:

public void saveOrUpdateEvents(List<Event> data) 
    realmInstance.executeTransaction(realm -> 
        for (Event event : data) 
            if (!TextUtils.isEmpty(event.date)) 
                Date date = DateUtils.getFullDate(event.date);
                Timber.d("date %s", date.toString());
                event.timestamp = date;
            
            Event cashedEvent = getEvent(event.id);
            if (cashedEvent.id != null) 
                event.eventClothingItems = cashedEvent.eventClothingItems;
                event.tags = cashedEvent.tags;
                event.location = cashedEvent.location;
            
        
        realm.delete(Event.class);
        realm.insertOrUpdate(data);
    );




public void clearClothingItems() 
    realmInstance.executeTransaction(realm -> 
        realm.delete(ClothingItem.class);
    );

【问题讨论】:

恕我直言,我会在 .map 之前向您推荐 .subscribeOn(Schedulers.io()).observeOn(Schedulers.io()) 地图功能有两个,在哪一个之前? 我要在他们俩面前说,我不是专家,但你可以试试。 这是因为您的dbProvider 没有考虑到 Realm 实例是线程本地的,因此您绑定到 UI 线程。但是我必须修改dbProvider 中的代码来解决这个问题。 怎么修改?我应该改变什么 【参考方案1】:

试试这个:

public Flowable<List<ClothingItem>> getClothingItemsRemote() 
    return clothingService.getAll("Bearer " + preferencesManager.getToken())         
            .subscribeOn(Schedulers.io())   
            .map(response -> response.items) 
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSuccess(clothingItems -> 
                dbProvider.clearClothingItems();
                dbProvider.saveOrUpdateClothingItems(clothingItems);
            )     
            .observeOn(Schedulers.computation())
            .toFlowable()
            .map(remoteItems -> dbProvider.getClothingItems(mSortType));

【讨论】:

我遇到了这个错误:java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. @Dr4ketheb4dass 我已经编辑了答案,你也可以添加getAll()方法的代码吗? 我添加了 getAll() 方法,并进行了更改,但我仍然有同样的错误 你到底是从哪里得到这个错误的?有什么线吗?可以分享一下领域相关的代码吗? 你需要在后台线程上打开Realm才能在后台线程上使用(然后你还必须严格确保完成后正确关闭)

以上是关于RxJava 和 Realm 请求使应用程序跳帧的主要内容,如果未能解决你的问题,请参考以下文章

sdk 16(果冻豆)上的领域,没有 rxjava 崩溃

RxJava - 链接请求和更新 UI

使用 rxJava 和改造多次调用另一个请求中的请求

如何在 SwiftUI 中使用 Realm

编舞跳帧!多少算太多?

从网络和数据库获取请求 rxJava