gpt4 book ai didi

android - MutableLiveData 未在 UI 中更新

转载 作者:行者123 更新时间:2023-12-03 13:25:09 27 4
gpt4 key购买 nike

更新:
如果我移动到另一个 fragment 并返回到这个 fragment ,则 TextView 会更新......

我无法通过使用 setValue() 或 postValue() 让 UI 中的 MutableLiveData 更新为新值。我可以通过将 MutableLiveData 更改为 ObservableData 来实现这一点,但重点是使用 LiveData 而不是 ObservableData。

我在其他 View 中也有类似的事情,没有问题。不确定这里发生了什么......我唯一能想到的是我在相机 Activity (通过 Intent )和这个 fragment 之间来回跳跃。在 Activity 结果中,我将 fragment 中的数据设置为 ViewModel。

我不相信我需要为 fragment 中的值设置任何观察者,因为我在 XML 和 ViewModel 之间有 2 路数据绑定(bind)。

my_fragment.XML

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
<variable
name="myViewModel"
type="com.example.myapplication.MyViewModel" />
</data>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={myViewModel.photosCount}"
tools:text="1" />

<Button
android:id="@+id/btnTakePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take Picture"
android:onClick="@{myViewModel::navClicked}"/>

</LinearLayout>

</layout>

MyViewModel.java
private MutableLiveData<String> photosCount = new MutableLiveData<>();
private MutableLiveData<Boolean> takePhoto = new MutableLiveData<>();

public MyViewModel() {
photosCount.setValue("0"); // This correctly sets the value to "0" in UI
takePhoto.setValue(true);
}

public MutableLiveData<String> getPhotosCount() {
return photosCount;
}

public MutableLiveData<Boolean> getTakePhoto() {
return takePhoto;
}

public void storeImage() {
....
Log.d(TAG, "Updating UI count to: " + String.valueOf(count)); // this shows the correct value that should be updated in the UI
photosCount.setValue(String.valueOf(count));
Log.d(TAG, "Updated value: " + photosCount.getValue()); // this shows the correct updated value
...
}

public void navClicked(@NonNull View view) {
if (view.getId() == R.id.btnTakePhoto) {
takePhoto.setValue(true);
}
}


现在,由于 LiveData 不保证在更改值时更新 UI,我认为这可能是绑定(bind)调度问题。那还没有解决这个问题......

MyFragment.java
private MyViewModel myViewModel;
MyFragmentBinding binding;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);

myViewModel = new ViewModelProvider(this).get(MyViewModel.class);

binding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false);
binding.setMyViewModel(myViewModel);

return binding.getRoot();
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
viewModel.getTakePhoto().observe(getViewLifecycleOwner(), takePhoto -> {
if (takePhoto) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
File photo = viewModel.createImageFile();
if (photo != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),"com.example.fileprovider", photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
this.startActivityForResult(intent, Constants.RequestCodes.MY_REQUEST_IMAGE_CAPTURE);
}
}
}
});
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == Constants.RequestCodes.MY_REQUEST_IMAGE_CAPTURE) {
viewModel.storeImage();
}
}
}

同样,如果您将 photosCount 从 MutableLiveData 切换到 ObservableData,则问题已得到解决,但这不是 LiveData。

最佳答案

I am unable to get the MutableLiveData in the UI to update to a new value either by using setValue() or postValue(). I can get this to work by changing the MutableLiveData to ObservableData but the point is to use LiveData not ObservableData.



您可能没有为您的 binding 设置生命周期所有者。目的。来自 JAVADOC对于 setLifecycleOwner()这个假设听起来更有说服力(请看 here):

If a LiveData is in one of the binding expressions and no LifecycleOwner is set, the LiveData will not be observed and updates to it will not be propagated to the UI.



因此,我仔细查看了您的代码。

观察

我注意到你没有展示你的 ViewModel并创建绑定(bind)。因此,我创建了一个满足您要求并正确更新 UI 的简单项目 - setValuepostValueLiveData正在更改相应的 View值无缝。然后,我根据我的工作示例填写了您的代码中缺少的部分。请参阅下面的更新代码。

相关代码

主视图型号
public class MainViewModel extends ViewModel {
private MutableLiveData<String> photosCount = new MutableLiveData<>();
private MutableLiveData<Boolean> takePhoto = new MutableLiveData<>();

public MainViewModel() {
photosCount.setValue("0");
takePhoto.setValue(true);
}

public MutableLiveData<String> getPhotosCount() {
return photosCount;
}

public MutableLiveData<Boolean> getTakePhoto() {
return takePhoto;
}

public void createImageFile() {
...
photosCount.setValue(String.valueOf(count));
...
}
...
}

fragment_main.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="MainViewModel"/>
</data>

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@={viewModel.photosCount}" />
</LinearLayout>
</layout>

主要 fragment
public class MainFragment extends Fragment {
private MainViewModel mainViewModel;
private FragmentMainBinding binding;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main, container,
false);
binding.setLifecycleOwner(this);

mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
binding.setViewModel(mainViewModel);

return binding.getRoot();
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

mainViewModel.getTakePhoto().observe(getViewLifecycleOwner(), takePhoto -> {
if (takePhoto) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
File photo = mainViewModel.storeImage();
if (photo != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),"com.example.fileprovider", photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
this.startActivityForResult(intent, 0);
}
}
}
});
binding.executePendingBindings();
}
}

结论

请注意,必须为 binding 设置生命周期所有者。如 binding.setLifecycleOwner(this) . MainViewModel必须为 binding 设置也。否则,它将无法正常工作。如有疑问,请务必查看官方文档 here .

关于android - MutableLiveData 未在 UI 中更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59545195/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com