【问题标题】:The app is freezing for a little bit when using Retrofit with RxJava使用 Retrofit 和 RxJava 时,应用程序会冻结一点
【发布时间】:2021-12-30 14:52:58
【问题描述】:

JSON

[
   {
      "countryName":"..."
   },
   {
      "countryName":"..."
   },
   {
      "countryName":"..."
   } //etc... to 195 countries
]

界面

public interface RetrofitInterface {

    @GET("GetCountries.php")
    Single<List<CountryModel>> getCountries();

}

代码

new Retrofit.Builder().baseUrl(Constants.BASE_URL).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava3CallAdapterFactory.create()).build().create(RetrofitInterface.class).getCountries().doOnSuccess(countryModels - > {
    for (CountryModel item: countryModels) {
        Chip chip = new Chip(requireContext());
        chip.setText(item.getCountryName());
        fragmentCountriesBinding.fragmentCountriesChipGroupMain.addView(chip);
    }
}).observeOn(AndroidSchedulers.mainThread()).subscribe(new SingleObserver < List < CountryModel >> () {
    @Override
    public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
        
    }

    @Override
    public void onSuccess(@io.reactivex.rxjava3.annotations.NonNull List < CountryModel > countryModels) {
        
    }

    @Override
    public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
        
    }
});

我正在尝试将 195 个国家/地区添加到 ChipGroup,但在添加芯片期间应用程序会冻结一点,首先doOnSuccess 方法中的代码在 onSuccess 方法中,但应用程序是冻结了一点,因此代码已移至 doOnSuccess 方法,但我收到此消息 只有创建视图层次结构的原始线程才能触及其视图。

我是 RxJava 新手,有什么解决方案吗?

【问题讨论】:

  • mmm 我不使用 Rx,但也许你可以使用新的 Handler(Looper.getMainLooper()) 并使用 post 方法来填充和显示芯片

标签: android retrofit retrofit2 rx-java rx-android


【解决方案1】:

您忘记为应该订阅的内容设置调度程序。 默认情况下,一个 Observable 和你应用到它的操作符链将在调用它的订阅方法的同一个线程上完成它的工作,并通知它的观察者。 所以如果你从主线程调用它,它将在主线程上执行。这就是为什么您的应用程序冻结的原因,因为您在负责 UI 的主线程上发出网络请求。

要修复它,只需使用 subscribeOn 方法设置另一个调度程序:

 .subscribeOn(Schedulers.io())

所以在你的情况下,它应该看起来像这样:

getCountries().doOnSuccess(countryModels - > {
    ...
}).observeOn(AndroidSchedulers.mainThread())
  .subscribeOn(Schedulers.io())   // Asynchronously subscribes  to the observable on the IO scheduler.
  .subscribe(

    ...

)

详细文档: https://reactivex.io/documentation/operators/subscribeon.html

还有有助于理解 RxJava 中的线程处理的文章: https://proandroiddev.com/understanding-rxjava-subscribeon-and-observeon-744b0c6a41ea

【讨论】:

  • 只有创建视图层次结构的原始线程才能触及它的视图。我试图通过这样做来跳过这个问题,但同样的事情应用程序有点冻结。看图ibb.co/kSjrgQ4
  • 是的,我明白了。在您的情况下,您会在 onSuccess 中同时添加很多视图。在你提到的关于 27 个国家的评论中。您有内部循环:对于 0 到 50 对于(CountryModel 芯片:countrymodels)因此,如果 countrtymodels.size =27 那么您将 27*50 = 1350 个项目添加到数组中。您可以检查它,只需在 onSuccess 方法中记录chips.size 值。如果它真的大于 1000 你创建一个视图并将其添加到视图层次结构中,创建和添加 1350 个视图是一个非常大的操作。在这种情况下,您应该考虑使用 RecyclerView 来显示项目列表。
  • RecyclerView 经过优化,可以处理大数据数组。有关 Recycler 视图使用的更多详细信息,您可以在官方文档中找到:developer.android.com/guide/topics/ui/layout/recyclerview
  • 是的,我已经在考虑切换到 RecyclerView 并仅将 Chips 用于小数据(1 到 10 个芯片)。
  • 我无法接受您的回答,因为我丢失了 SE19 帐户。但我会在 6 小时后给你赏金。谢谢
猜你喜欢
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-16
  • 2011-08-16
  • 2017-10-03
相关资源
最近更新 更多