Как обновить фрагменты Viewmodels в MainActivity? - PullRequest
0 голосов
/ 03 ноября 2018

У меня есть 3 одинаковых фрагмента в ViewPager, каждый из которых содержит 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 есть ящик, содержащий платформы для фильтрации, например, с ПК, Xbox и PS4, и когда пользователь закрывает ящик, я хочу, чтобы все мои 3 фрагмента корректно обновились, возможно ли это сделать с помощью viewmodel? Например, как я могу наблюдать за изменениями списка и платформ? Ящик в Основном действии добавляет выбранные платформы в список Integer, например, PS4 имеет идентификатор 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 голосов
/ 05 ноября 2018

Все, что вы можете сделать, если вы хотите поделиться ViewModel от деятельности и повторно использовать его во фрагменте, используя его активность context .

Итак, на Уровень активности используйте как показано ниже:

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

И когда вызывается событие закрытия вашего ящика, используйте этот объект mReleasesViewModel для вызова метода загрузки:

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

Теперь для Уровень фрагмента используйте тот же объект ViewModel, который использовался в действии, с context , как показано ниже:

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);
    }
});

Дайте мне знать, если все еще нужны какие-либо подробные объяснения, я соответствующим образом отредактирую свой ответ.

0 голосов
/ 03 ноября 2018

Создайте только 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);
        }
    }); 
...