如何从另一个活动刷新viewModel livedata

4

我正在开发Android应用程序,想要从第二个活动中刷新viewModel livedata。当我返回到第一个活动时,数据没有被刷新。

第一个活动:

 mViewModel = ViewModelProviders.of(this).get(MenuViewModel.class);

mViewModel.getMenus().observe(this, menuResponse -> {
            if (menuResponse != null) {
                resMenus.addAll(menuResponse.getMenus());
                progressBar.setVisibility(View.GONE);
                mAdapter.notifyDataSetChanged();
            }
        });

菜单视图模型:

public class MenuViewModel extends AndroidViewModel {
    private MutableLiveData<MenuResponse> restMenuData;
    private MenusRepository mRepository;

    public MainActivityViewModel(@NonNull Application application) {
        super(application);
        mRepository = MenusRepository.getInstance(application);
        restMenuData = mRepository.getMenus();
    }

    public LiveData<MenuResponse> getMenus() {
        return restMenuData;
    }
}

菜单仓库

 private MenusRepository(Context context) {
        apiRequest= RetrofitInstance.getInstance(context).getApiRequest();
    }

    public synchronized static MenusRepository getInstance(Context context) {
        if (projectRepository == null) {
            projectRepository = new MenusRepository(context);
        }
        return projectRepository;
    }

public MutableLiveData<MenuResponse> getMenus() {
        final MutableLiveData<MenuResponse> data = new MutableLiveData<>();
        apiRequest.getMenus().enqueue(new Callback<MenuResponse>() {
            @Override
            public void onResponse(@NonNull Call<MenuResponse> call, @NonNull Response<MenuResponse> response) {
                if (response.isSuccessful() && response.body() != null) {
                    data.setValue(response.body());
                }
            }

            @Override
            public void onFailure(@NonNull Call<MenuResponse> call, @NonNull Throwable t) {
                data.setValue(null);
            }
        });
        return data;
    }

第二个活动:

MenuViewModel mViewModel = ViewModelProviders.of(Objects.requireNonNull(SecondActivity.this)).get(MenuViewModel.class);
        mViewModel.getMenus();
// This line not refresh menus

我希望能够从视图模型中刷新数据,但它返回的是旧数据。在最佳实践中,如何刷新视图模型数据?

2个回答

3
MenusRepository.getMenus() 方法每次调用都会创建一个新的 LiveData 实例,这并不是正确的做法。你应该只有一个 LiveData 实例,并让不同的对象(活动、视图模型等)订阅它。
你可以这样做 - 创建一个 MenusRepository 的单例(我认为你已经做了)。只创建一个 MutableLiveData 实例,并使用它来更新数据。
class MenusRepository {
    private val liveData = MutableLiveData<MenuResponse>()

    fun getMenus() {
        // Your api call. Do not create a new instance of the livedata.
    }

    fun menus(): LiveData<MenuResponse> {
        return liveData
    }

    fun update(data: MenuResponse) {
        liveData.post(data)
    }

这段代码是Kotlin语言,但同样适用于Java。
您可以使用update方法来发布LiveData的更新。当您更新时,所有观察者都将接收到新数据。在ViewModel中使用MenusRepository.menus()来访问LiveData。
更新
您的MenuRepository类可能如下所示。
private final MutableLiveData<MenuResponse> liveData = new MutableData<>();
private MenusRepository(Context context) {
    apiRequest= RetrofitInstance.getInstance(context).getApiRequest();
}

public synchronized static MenusRepository getInstance(Context context) {
    if (projectRepository == null) {
        projectRepository = new MenusRepository(context);
    }
    return projectRepository;
}

public MutableLiveData<MenuResponse> loadMenus() {
    apiRequest.getMenus().enqueue(new Callback<MenuResponse>() {
        @Override
        public void onResponse(@NonNull Call<MenuResponse> call, @NonNull Response<MenuResponse> response) {
            if (response.isSuccessful() && response.body() != null) {
                liveData.setValue(response.body());
            }
        }

        @Override
        public void onFailure(@NonNull Call<MenuResponse> call, @NonNull Throwable t) {
            liveData.setValue(null);
        }
    });
}

public LiveData<MenuResponse> getMenus() {
    return liveData;
}

public void updateData(response: MenuResponse) {
    liveData.postValue(response);
}
  • 如果你想手动更新数据(从另一个活动中),请使用 menuRepository.update() 方法。这将向你的 LiveData 发送数据,然后更新所有观察者,即 ViewModel。
  • 当你要使用 API 获取数据时,请调用 menuRepository.loadMenu()
  • 使用 menuRepository.getMenus() 获取 LiveData 并附加你的观察者。

由于 MenuRepository 是单例模式,只有一个 LiveData 实例。当您向此 LiveData 实例发布更新时,所有观察者都将接收到新数据。


我正在编辑存储库类,你能给我一个例子吗? - Benfactor
1
@Benfactor,为什么你说你不能从另一个活动更新数据?你没有更新ViewModel数据,而是要求你的存储库更新数据。如代码片段中所述,请调用MenuRepository.getInstance().updateData(data),其中data是更新后的数据。如果你的意思是想从另一个活动发起API调用来更新数据,请使用loadMenu()方法。 - Froyo
是的。基本上,您想要从第二个活动更新数据的问题。您想要更新什么? - Froyo
让我们在聊天中继续这个讨论 - Benfactor
@Froyo,嗯,不是静态的。但是在ViewModel之外的LiveData。 - Mooing Duck
显示剩余4条评论

0
public class MenuViewModel extends AndroidViewModel {
private MutableLiveData<MenuResponse> restMenuData;
private MenusRepository mRepository;

public MainActivityViewModel(@NonNull Application application) {
    super(application);
    mRepository = MenusRepository.getInstance(application);
    restMenuData = mRepository.getMenus();
}

public LiveData<MenuResponse> getMenus() {
    restMenuData = new MutableLiveData<>();
    return restMenuData;
}
}

将视图模型代码更改如上所示。 以便在返回活动之前始终清除实时数据。

这使得它清楚地表明这是一个视图模型,而不是一个存储库。我有许多ViewModels,它们都应该访问相同的存储库,但我不知道如何设置存储库以便能够更新LiveData对象。 - Mooing Duck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接