【问题标题】:Why Injecting objects and making api calls in io() thread slows opening the Fragment?为什么在 io() 线程中注入对象并进行 api 调用会减慢 Fragment 的打开速度?
【发布时间】:2017-10-01 14:59:34
【问题描述】:

在 VacationFragment 的 onAttach() 中,我从 VacationViewModel -> VacationRepository 调用 featuresDays() , 当我单击导航到VacationFragment 的视图时,我注意到它以延迟打开,我正在等待几毫秒直到它打开VacationFragment。 当我评论vacationViewModel.featureDays(startDate,endDate) 它会毫不拖延地打开 Fragment

class MainApplication : Application(), HasActivityInjector, HasSupportFragmentInjector {
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.builder().androidModule(AndroidModule(this)).build()
appComponent.inject(this)
}

class VacationFragment : Fragment() {

   override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
vacationViewModel = ViewModelProviders.of(activity, icaViewModelFactory).get(VacationViewModel::class.java)
vacationViewModel.featureDays(startDate,endDate)}
 }

class VacationViewModel : ViewModel(), AppComponent.Injectable {

 private val disposables: CompositeDisposable = CompositeDisposable()

  @Inject
lateinit var vacationRepository: VacationRepository
 val featuredFeaturedCalendar: MediatorLiveData<FeaturedCalendar> = MediatorLiveData()

fun featureDays(from: String, till: String) {

val disposable = vacationRepository
    .featuredCalendar(from, till, KEY, ID)
    .map { featuredCalendar ->
      val holidays = arrayListOf<FeaturedCalendar.Holiday>()
      featuredCalendar.holidays.forEach { holidayItem ->
        val holiday = FeaturedCalendar.Holiday(format.parse(holidayItem.date), holidayItem.holiday)
        holidays.add(holiday)
      }
      FeaturedCalendar(featuredCalendar.status, holidays)
    }
    .subscribeOn(Schedulers.io())
    .observeOn(mainThread())
    .subscribe(
        {
          featuredFeaturedCalendar.postValue(it)
        },
        {
          throw IllegalStateException(it)
        })

  disposables.add(disposable)
}}


class VacationRepository(private val apiDaysSeResource: ApiDaysSeResource) {

  fun featuredCalendar(from: String, till: String, key: String, id: String): Flowable<FeaturedCalendar> {
return apiDaysSeResource.days(from, till, key, id)//.toFlowable()
  }

}

public interface ApiDaysSeResource {
 Flowable<FeaturedCalendar> days(@Query("fran") String fran, @Query("till") String till, @Query("key") String key, @Query("id") String id);
}

【问题讨论】:

  • 一些可能的原因 - 1. map() 发生在原始线程上,2. observeOn() 可能正在做一些非常慢的事情。订阅后一次性真的可以null吗?不要认为你需要那张支票。
  • @milosmns 我去掉了检查的部分,如果我注释 map() 部分和这行代码 featuresFeaturedCalendar.postValue(it) 一样,没有区别
  • 嗯。好吧,也许是模型有点慢?也许你的onAttach() 做了一些减慢它的事情?
  • 我已经把vacationViewModel.featureDays(startDate,endDate) 的调用移到onResume() .onCreate 没有区别,但是你觉得onAttach() 有什么问题?
  • 但是如果我删除方法的调用它并不慢,它应该可以正常工作

标签: android rx-java retrofit2 viewmodel dagger-2


【解决方案1】:

对于不会阅读 OP 中完整聊天/cmets 部分的任何人 - 问题在于 ApiDaysSeResource 类,它的创建需要很长时间才能完成。由于注入在onAttach() 中同步发生,因此在启动时减速很明显。从 OP 所做的测试来看,减速似乎是 1.0 - 1.5 秒,这是很多。

如果你有空闲时间,我写了一篇关于这个问题的长文,以及当你无法访问需要很长时间才能完成的构造函数时如何异步注入单例。 Click here阅读文章。

基本思想是注入Observable&lt;YourSlowThing&gt; 而不是YourSlowThing - 这将允许您等待实例可用,但仍会在启动时获得非空依赖项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    相关资源
    最近更新 更多