android - ViewModel 中的延迟初始化方法
问题描述
我在 Github 有以下项目:https ://github.com/AliRezaeiii/TMDb-Paging
由于数据源未初始化,我必须在 ViewModel 中发布延迟调用方法:
abstract class DetailViewModel(private val item: TmdbItem) : BaseViewModel() {
private val handler = Handler(Looper.getMainLooper())
val trailers: ObservableList<Video> = ObservableArrayList()
val isTrailersVisible = ObservableBoolean(false)
private val _cast = MutableLiveData<List<Cast>>()
val cast: LiveData<List<Cast>> = _cast
val isCastVisible = ObservableBoolean(false)
init {
handler.postDelayed({
showTrailers()
showCast()
}, 100)
}
protected abstract fun getTrailers(id: Int): Observable<List<Video>>
protected abstract fun getCast(id: Int): Observable<List<Cast>>
private fun showTrailers() {
EspressoIdlingResource.increment() // App is busy until further notice
compositeDisposable.add(getTrailers(item.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doFinally {
if (!EspressoIdlingResource.getIdlingResource().isIdleNow) {
EspressoIdlingResource.decrement() // Set app as idle.
}
}
.subscribe({ videos ->
if (videos.isNotEmpty()) {
isTrailersVisible.set(true)
}
with(trailers) {
clear()
addAll(videos)
}
}
) { throwable -> Timber.e(throwable) })
}
private fun showCast() {
EspressoIdlingResource.increment() // App is busy until further notice
compositeDisposable.add(getCast(item.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doFinally {
if (!EspressoIdlingResource.getIdlingResource().isIdleNow) {
EspressoIdlingResource.decrement() // Set app as idle.
}
}
.subscribe({ cast ->
if (cast.isNotEmpty()) {
isCastVisible.set(true)
}
this._cast.postValue(cast)
}
) { throwable -> Timber.e(throwable) })
}
}
这是我的片段:
abstract class DetailFragment<T : TmdbItem>
: BaseDaggerFragment(), CastClickCallback {
protected abstract fun getViewModel(): DetailViewModel
protected abstract fun getLayoutId(): Int
protected abstract fun initViewBinding(root: View): ViewDataBinding
protected abstract fun getTmdbItem(): T
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val viewModel = getViewModel()
val root = inflater.inflate(getLayoutId(), container, false)
initViewBinding(root).apply {
setVariable(BR.vm, viewModel)
lifecycleOwner = viewLifecycleOwner
}
with(root) {
with(activity as AppCompatActivity) {
setupActionBar(details_toolbar) {
setDisplayShowTitleEnabled(false)
setDisplayHomeAsUpEnabled(true)
setDisplayShowHomeEnabled(true)
}
}
summary_label.visibleGone(getTmdbItem().overview.trim().isNotEmpty())
// Make the MotionLayout draw behind the status bar
details_motion.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
summary.setOnClickListener {
val maxLine = resources.getInteger(R.integer.max_lines)
summary.maxLines = if (summary.maxLines > maxLine) maxLine else Int.MAX_VALUE
}
viewModel.cast.observe(viewLifecycleOwner, Observer {
it?.apply {
val adapter = CastAdapter(it, this@DetailFragment)
cast_list.apply {
setHasFixedSize(true)
cast_list.adapter = adapter
}
}
})
with(details_rv) {
postDelayed({ scrollTo(0, 0) }, 100)
}
}
return root
}
}
和 BaseDaggerFragment :
open class BaseDaggerFragment : DaggerFragment() {
@Inject
lateinit var dataSource: RemoteDataSource
}
可能是比以下更好的解决方案:
init {
handler.postDelayed({
showTrailers()
showCast()
}, 100)
}
解决方案
您可以像这样延迟初始化
private val users:MutableLiveData<List<Cast>> by lazy {
MutableLiveData().also {
showTrailers()
showCast()
}
}
更多细节参考ViewModel
推荐阅读
- .net - .NET 中可用的序列化程序
- c++ - 如何用前导零和四舍五入的小数格式化双精度
- c# - 操作返回无效状态代码“禁止”-PowerBi 应用拥有数据
- hyperledger-fabric - InMemoryWallet 中的 Hyperledger Fabric 导入身份
- java - RMI 将对象绑定到注册表并从客户端访问
- c# - 为什么在尝试获取 log4net 日志记录级别时会出现“对象引用”错误?
- azure-devops - 远程安装自托管代理并希望使其成为活动代理并需要关联它以构建管道
- c++ - 使用 lambda 删除器返回唯一指针时可能出现悬空引用
- outlook-web-addins - Office.context.mailbox.item.notificationMessages
- c# - 进入信标范围和离开信标范围时的事件