Android Fragment中LiveData观察者未被调用问题求助
LiveData值已改变但Observer未被调用的问题排查
尽管LiveData的值已经改变,但我的Observer并未被调用。请问我哪里操作有误?观察者和ViewModel均在Fragment中初始化,通过按钮调用ViewModel中的方法(计算后调用设置方法)修改值,但观察者并未监测到ViewModel值的变化。
Fragment代码
public class PlayerFragment extends Fragment { private PlayerViewModel mViewModel; private ImageButton volumeUp, volumeDown; public static PlayerFragment newInstance() { return new PlayerFragment(); } public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); volumeDown = getView().findViewById(R.id.btn_player_volume_down); volumeDown.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { mViewModel.volumeDown(); } }); volumeUp = getView().findViewById(R.id.btn_player_volume_up); volumeUp.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { mViewModel.volumeUp(); } }); final Observer<Integer> volumeObserver = new Observer<Integer>() { @Override public void onChanged(Integer volValue) { SeekBar volume = getView().findViewById(R.id.player_volumeBar); volume.setProgress( volValue ); } }; mViewModel.getVolume().observe(getViewLifecycleOwner(), volumeObserver); } @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { mViewModel = new ViewModelProvider(this).get(PlayerViewModel.class); return inflater.inflate(R.layout.fragment_player, container, false); } @Override public void onResume() { super.onResume(); ((MainActivity) getActivity()).getSupportActionBar().setTitle( getString(R.string.fragment_player_title) ); mViewModel.fetchPlayerData(); } }
ViewModel代码
public class PlayerViewModel extends ViewModel { private MutableLiveData<Integer> volume; public PlayerViewModel(){ volume = new MutableLiveData<Integer>(); fetchPlayerData(); } public void fetchPlayerData(){ volume = new MutableLiveData<Integer>(1); } public void volumeUp() { volume.postValue( volume.getValue() + 5 ); Log.i( "volumeUp", "Set new volume:" + volume.getValue().toString() ); } public void volumeDown() { volume.postValue( volume.getValue() - 5 ); Log.i( "volumeDown", "Set new volume:" + volume.getValue().toString() ); } }
问题原因及修复方案
核心错误1:LiveData实例被重复创建
你的fetchPlayerData()方法每次调用都会新建一个MutableLiveData对象并赋值给volume变量,导致Fragment订阅的旧LiveData实例和后续修改的新实例不是同一个对象,Observer自然无法收到更新通知。
修复:直接修改已有LiveData的值,不创建新对象:
public void fetchPlayerData(){ volume.setValue(1); }
核心错误2:缺少对外暴露LiveData的方法
Fragment中调用了mViewModel.getVolume(),但ViewModel未实现该方法,会导致编译错误,需要补充:
public LiveData<Integer> getVolume() { return volume; }
额外优化:简化ViewModel初始化逻辑
构造函数中可直接设置初始值,避免重复调用fetchPlayerData():
public PlayerViewModel(){ volume = new MutableLiveData<Integer>(); volume.setValue(1); // 直接设置初始值 }
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

