【问题标题】:Empty screen when Activity recreated重新创建 Activity 时屏幕为空
【发布时间】:2020-08-15 19:31:23
【问题描述】:

我正在 SplashActivity 中加载联系人:

private fun startMainActivity() {
        repository.loadContacts()
        handler.postDelayed({
            val intent =Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        }, SPLASH_DELAY.toLong())

这是我的存储库类:

@Singleton
class ContactsRepository @Inject constructor(
        private val context: Context,
        private val schedulerProvider: BaseSchedulerProvider) {

    private val compositeDisposable = CompositeDisposable()

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

    fun loadContacts() {
        _liveData.value = Resource.Loading()
        val cursor = context.contentResolver.query(
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                PROJECTION,
                null,
                null,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE UNICODE ASC")
        Observable.create(ObservableOnSubscribe<List<Contact>>
        { emitter -> emitter.onNext(ContactUtil.getContacts(cursor, context)) })
                .subscribeOn(schedulerProvider.io())
                .doOnComplete { cursor?.close() }
                .doFinally { compositeDisposable.clear() }
                .subscribe {
                    _liveData.postValue(Resource.Success(it))
                }.also { compositeDisposable.add(it) }
    }
}

在我的 MainFragment onCreateView 中,我在 viewModel 中观察 LiveData :

                // Create the observer which updates the UI.
                final Observer<Resource<List<Contact>>> contactsObserver = resource -> {
                    if (resource instanceof Resource.Success) {
                        mContacts = ((Resource.Success<List<Contact>>) resource).getData();
                        mAdapter.setItems(mContacts, true);
                    }
                };
    
                // Observe the LiveData, passing in this fragment as the LifecycleOwner and the observer.
                viewModel.getLiveData().observe(this, contactsObserver);
            }

这是我的 ViewModel 类:

class ContactsViewModel(repository: ContactsRepository) : ViewModel() {

    private val _liveData = repository.liveData
    val liveData: LiveData<Resource<List<Contact>>>
        get() = _liveData

    /**
     * Factory for constructing ContactsViewModel with parameter
     */
    class Factory @Inject constructor(
            private val repository: ContactsRepository
    ) : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(ContactsViewModel::class.java)) {
                @Suppress("UNCHECKED_CAST")
                return ContactsViewModel(repository) as T
            }
            throw IllegalArgumentException("Unable to construct viewmodel")
        }
    }
}

有时当我在很长一段时间后恢复 MainFragment 时,我会在 RecyclerView 中看到一个没有数据的空屏幕(例如,可能容器活动被操作系统杀死)。我的猜测是 repository.liveData.value 返回 null。这可能是任何其他问题。感谢您的建议。

附录:

@Inject
ContactsViewModel.Factory mFactory;

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    ContactsViewModel viewModel = new ViewModelProvider(this, mFactory).get(ContactsViewModel.class);
            ViewDataBinding binding = FragmentContactsBinding.bind(root);
            binding.setVariable(BR.vm, viewModel);
            binding.setLifecycleOwner(getViewLifecycleOwner());
}

完整的源代码在:https://github.com/AliRezaeiii/Contacts/blob/master/app/src/main/java/com/sample/android/contact/ui/ContactsFragment.java

【问题讨论】:

  • 看起来进程已终止,UI 已从保存的实例状态恢复。 ViewModel 将在配置更改后继续存在,但在进程死亡后不会恢复(如 Options for preserving UI state 中所述) Fragment 如何“获取” ViewModel?
  • 谢谢@BömachtBlau 我已将 ViewModel 初始化添加到问题的附录部分。

标签: android android-livedata android-viewmodel


【解决方案1】:

我意识到这是由于系统启动的进程死亡。因此,我在 ViewModel 的 init 方法中添加了以下行来解决此问题:

class ContactsViewModel(repository: ContactsRepository) : ViewModel() {

    private val _liveData = repository.liveData
    val liveData: LiveData<Resource<List<Contact>>>
        get() = _liveData

    init {
        // Reload contacts in case of system initiated process death
        if(liveData.value == null) {
            repository.loadContacts()
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-19
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    相关资源
    最近更新 更多