如何在MainActivity中更新Viewmodels片段?

时间:2018-11-03 05:27:54

标签: android android-fragments viewmodel

我在ViewPager中有3个相同的片段,每个片段都包含一个ViewModel,每当列表更改时,我都会在其中观察片段的更改。

这里是观察者;

    mReleasesViewModel = ViewModelProviders.of(this, new ReleasesViewModelFactory(filter)).get(ReleasesViewModel.class);
    // livedata
    mDatabaseLoading.setVisibility(View.VISIBLE);
    mReleasesViewModel.getUpcomingReleases().observe(this, new Observer<List<_Release>>() {
        @Override
        public void onChanged(@Nullable List<_Release> releases) {
            // whenever the list is changed
            if (releases != null) {
                mUpcomingGamesAdapter.setData(releases);
                mUpcomingGamesAdapter.notifyDataSetChanged();
            }
            mDatabaseLoading.setVisibility(View.GONE);
        }
    }); 

现在MainActivity中有一个抽屉,其中包含可以从PC,Xbox和PS4等进行过滤的平台,当用户关闭抽屉时,我希望我的所有3个片段都可以优雅地更新,这是否可以通过viewmodel完成?像我如何观察列表更改和平台更改? “主活动”中的抽屉会将所选平台添加到Integer列表中,例如PS4的ID为3

我的ViewModel:

public class ReleasesViewModel extends ViewModel {
    public static final String TAG = ViewModel.class.getSimpleName();
    // Example: Whenever the value contained by this MutableLiveData changes, we will set the contained value to our TextView
    // Livedata objects will usually be kept in the ViewModel class
    private MutableLiveData<List<_Release>> upcomingReleases;
    // this field [mMonthYearFilter] is passed by our fragment to the AndroidViewModel
    // to pass additional argument to my custom AndroidViewModel I need a AndroidViewModelFactory
    private String monthYearFilter;
    private ReleasesRepository releasesRepository;

    public ReleasesViewModel(String monthYearFilter) {
        this.monthYearFilter = monthYearFilter;
    }

    public MutableLiveData<List<_Release>> getUpcomingReleases() {
        if (upcomingReleases == null) {

            upcomingReleases = new MutableLiveData<>();

            // User settings region & platforms
            String region = SharedPrefManager.read(SharedPrefManager.KEY_PREF_REGION, "North America");
            Set<String> defaultPlatformsSet = new HashSet<>();
            ArrayList<Integer> platforms = SharedPrefManager.read(SharedPrefManager.PLATFORM_IDS, defaultPlatformsSet);

            releasesRepository = new ReleasesRepository(region, monthYearFilter, platforms);
            loadReleases();
        }
        return upcomingReleases;
    }


    private void loadReleases() {
        releasesRepository.addListener(new FirebaseDatabaseRepository.FirebaseDatabaseRepositoryCallback<_Release>() {
            @Override
            public void onSuccess(List<_Release> result) {
                upcomingReleases.setValue(result);
            }

            @Override
            public void onError(Exception e) {
                Log.e(TAG, e.getMessage());
                upcomingReleases.setValue(null);
            }
        });
    }
}

2 个答案:

答案 0 :(得分:1)

在活动级别仅创建1个ViewModel并将其传递给片段。您的ViewModel可以为每个片段提供3个LiveData服务。假设您在一个片段中显示即将发布的版本,而在另一个片段中显示已经发布的游戏。因此,就像您即将发布的版本一样,请在ViewModel中创建另一个方法,然后返回LiveData,该方法将保存已发布游戏的列表。

在下面的代码mViewModel中将传递给片段的视图模型。

mViewModel.getReleasedGames().observe(this, new Observer<List<_Release>>() {
        @Override
        public void onChanged(@Nullable List<_Release> released_games) {
            // whenever the list is changed
            if (released_games != null) {
                mReleasedGamesAdapter.setData(releases);
                mReleasedGamesAdapter.notifyDataSetChanged();
            }
            mDatabaseLoading.setVisibility(View.GONE);
        }
    }); 

答案 1 :(得分:1)

  

如果您想分享活动中的ViewModel,您所能做的就是   并使用其活动 context 对其进行分段重用。

因此,在活动级别上,请按以下方式使用:

mReleasesViewModel = ViewModelProviders.of(this, new ReleasesViewModelFactory(filter)).get(ReleasesViewModel.class); // this will make ViewModel on activity level.

当您的抽屉关闭事件被调用时,请使用此mReleasesViewModel对象来调用您的load方法:

mReleasesViewModel.loadReleases(); // This will provide your list data to your LiveData object while observing on fragments.

现在,对于片段级别,使用活动上使用的ViewModel相同的对象,其上下文如下所示:

mReleasesViewModel = ViewModelProviders.of(getActivity()).get(ReleasesViewModel.class); // this will make same ViewModel object on fragment level as activity.

观察者调用的其余部分将如下所示:

mReleasesViewModel.getUpcomingReleases().observe(this, new Observer<List<_Release>>() {
    @Override
    public void onChanged(@Nullable List<_Release> releases) {
        // whenever the list is changed
        if (releases != null) {
            mUpcomingGamesAdapter.setData(releases);
            mUpcomingGamesAdapter.notifyDataSetChanged();
        }
        mDatabaseLoading.setVisibility(View.GONE);
    }
});

让我知道是否仍然需要任何详细的说明,我将相应地修改答案。