通用参数化基础 ViewModel

Generic Parameterized Base ViewModel

我的 ViewModel 有以下基础 class:

abstract class BaseViewModel<T, R>(private val schedulerProvider: BaseSchedulerProvider) :
    ViewModel() {

    private val compositeDisposable = CompositeDisposable()

    private val _liveData = MutableLiveData<Resource<T>>()
    val liveData: LiveData<Resource<T>>
        get() = _liveData

    protected abstract val requestObservable: Observable<R>

    protected abstract fun getSuccessResult(it: R): T

    init {
        Handler().postDelayed({
            sendRequest()
        }, 1)
    }

    fun sendRequest() {
        _liveData.value = Resource.Loading()
        composeObservable { requestObservable }
            .subscribe({
                _liveData.postValue(Resource.Success(getSuccessResult(it)))
            }) {
                _liveData.postValue(Resource.Failure(it.localizedMessage))
                Timber.e(it)
            }.also { compositeDisposable.add(it) }
    }

    private fun <T> composeObservable(task: () -> Observable<T>): Observable<T> = task()
        .doOnSubscribe { EspressoIdlingResource.increment() } // App is busy until further notice
        .subscribeOn(schedulerProvider.io())
        .observeOn(schedulerProvider.ui())
        .doFinally {
            if (!EspressoIdlingResource.countingIdlingResource.isIdleNow) {
                EspressoIdlingResource.decrement() // Set app as idle.
            }
        }

下面是我在 Fragment 中初始化 ViewModel 的方式:

class MainFragment @Inject
constructor() // Required empty public constructor
    : DaggerFragment() {

    @Inject
    lateinit var factory: MainViewModel.Factory

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {

            val viewModel = ViewModelProvider(this, factory).get(MainViewModel::class.java)
}

如您所见,我在 init 块中有以下延迟:

Handler().postDelayed({
                sendRequest()
            }, 1)

如果没有此延迟,应用程序会崩溃,因为 api 在继承的 class 中将为空:

    class MainViewModel(
        api: PokemonService,
        schedulerProvider: BaseSchedulerProvider
    ) : BaseViewModel<List<Pokemon>, List<NamedResponseModel>>(schedulerProvider) {

override val requestObservable: Observable<List<NamedResponseModel>> =
        api.getPokemonList(LIMIT).map { it.results }
}

如果我不使用通用参数化 ViewModel,则不需要延迟。您可以在以下位置找到存储库:https://github.com/AliRezaeiii/Pokemon

为什么我需要延迟,避免延迟的解决方案是什么?

问题出在 class 的初始化程序的执行顺序上。这是引自 this article.

First, default constructor arguments are evaluated, starting with argument to the constructor you call directly, followed by arguments to any delegated constructors. Next, initializers (property initializers and init blocks) are executed in the order that they are defined in the class, top-to-bottom. Finally, constructors are executed, starting with the primary constructor and moving outward through delegated constructors until the constructor that you called is executed. The constructor order is probably the most surprising, since no matter where in the class the constructor is defined, it is always executed after all initializers have run.

详情请查看文章