【问题标题】:LiveData deactivates observer in Fragment after popping it up from backstackLiveData 在从后台弹出后停用 Fragment 中的观察者
【发布时间】:2026-01-24 09:15:02
【问题描述】:

每次用户访问HomeFragment 时,我都需要执行一项任务。不管它是新创建的还是用户回到这个Fragment

新创建时它工作正常,但从返回堆栈返回时不会调用观察者。我使用调试器发现LiveData 有观察者,hasActiveObservers() 返回 false。我试图从不同的生命周期回调中操作和观察/删除Observer,但没有成功。在 Google 中也找不到明确的解释。

这是我的HomeFragment.java

public class HomeFragment extends BaseFragment {
    //.......
    private ImportViewModel viewModel;

    private Observer<State> observer = state -> {
        //update UI depending on a state
    };

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(ImportViewModel.class);
        observeViewModel();
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_home, container, false);

        //execute here since onCreate() is not called when coming from backstack
        viewModel.importFile();

        return v;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        viewModel.liveDataState.removeObserver(observer);
    }

    private void observeViewModel() {
        viewModel.liveDataState.observe(this, observer);
    }

    //.......
}

还有ImportViewModel.java

public class ImportViewModel extends ViewModel {

    //......
    public MutableLiveData<State> liveDataState = new MutableLiveData<>();
    //......
    public void importFile(){
        disposables.add(repository.importFile()
                .subscribeOn(subscribeOnScheduler)
                .observeOn(observeOnScheduler)
                .subscribe(this::onNext, this::onError, this::onComplete));
    }

     private void onNext(SomeResponse resp){
        liveDataState.setValue(new State(resp));
    }

    private void onError(Throwable t){
        liveDataState.setValue(new ErrorState(t.getMessage()));
    }

    private void onComplete(){
        liveDataState.setValue(new CompleteState());
    }
}

为什么观察者变得不活跃?

【问题讨论】:

  • onCreateView 应该在来自 backstack 时调用?
  • @PavelPoley,是的。它被称为。
  • 你在 HomeFragment 上面使用 FragmentManager().beginTransaction().add() 或 replace() 吗?
  • @PavelPoley,我愿意replace。我测试了生命周期,并且可以肯定没有删除观察者,因为没有调用 onDestroy 并且它以 onCreateView 开头
  • 所以如果你回去 onCreate 没有被调用而 onCreateView 被调用了?

标签: android viewmodel android-lifecycle android-architecture-components android-livedata


【解决方案1】:

我遇到了类似的问题。我的情况是我要从主片段转到另一个片段,我通过将片段视图设置为全局和在创建视图方法中维护片段的状态,我首先检查视图是否不为空,然后不设置任何内容。在那之前工作正常。

我的问题是当我从那个片段回来时,没有观察到实时数据的变化。

我设法以这种方式在 onResume 方法中做到了。

private fun setupObserver() {
        val observer: Observer<MutableList<Post>> = Observer {
            //            textView.text = homeViewModel.text.value?.get(0)?.name ?: "Loading"
            Log.d(
                AppConstants.GLOBAL_LOGTAG,
                "observed with current page = ${homeViewModel.getMetaData().currentPage}"
            )
            //logic to show progress

            if (!isObservedAtLeastOneTime) {
                showProgress()
            }
            if (homeViewModel.getMetaData().currentPage == 1) {
                list.clear()
                list.addAll(homeViewModel.mutableLiveData.value!!)
                recentPostsAdapter.notifyDataSetChanged()
            } else {
                list.clear()
                list.addAll(homeViewModel.mutableLiveData.value!!)
                recentPostsAdapter.notifyDataSetChanged()
            }
            if (isObservedAtLeastOneTime) {
                hideProgressAndShowContent()
            }
            isObservedAtLeastOneTime = true
            isLoading = false
            swipeRefreshLayout.isRefreshing = false
        }
        if (!homeViewModel.mutableLiveData.hasActiveObservers()) {
            homeViewModel.mutableLiveData.observe(viewLifecycleOwner, observer)
        }
    }

在恢复方法中。

override fun onResume() {
        super.onResume()
        if(!homeViewModel.mutableLiveData.hasActiveObservers()){
            setupObserver()
        }
    }

【讨论】: