Как реализовать диалоговую опцию выбора в архитектуре Android MVVM

1

Я пытаюсь войти в шаблон MVVM, и моя проблема в том, что я не совсем уверен, правильно ли я его использую. View отвечает за все операции пользовательского интерфейса (например, show stuff?), Но что происходит, когда нам нужно что-то изменить в логике.

Так что я действительно хочу показать диалог с определенными опциями, выбрать один и перезагрузить приложение.

Я реализовал функции в классе MainActivity, и я использую mCountrySelection.show(), когда необходимо действие.

    public void createCountriesDialog()
    {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
        dialogBuilder.setTitle("Available Countries");

        GridView gridView = new GridView(MainActivity.this);
        final String[] countries = getResources().getStringArray(R.array.countries);
        final String[] codes = getResources().getStringArray(R.array.codes);
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, countries);
        gridView.setAdapter(arrayAdapter);

        dialogBuilder.setView(gridView);
        dialogBuilder.setNegativeButton("Close", new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                dialog.dismiss();
            }
        });

        mCountrySelection = dialogBuilder.create();

        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                PreferencesManager.setCountry(countries[position], codes[position]);
                getSupportActionBar().setTitle(PreferencesManager.getCountry());

                FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.a_main_frame, new ArticlesFragment(), "ArticlesFragment");
                fragmentTransaction.commit();

                mCountrySelection.dismiss();
            }
        });
    }

    public void createAboutDialog()
    {
        AlertDialog.Builder aboutBuilder = new AlertDialog.Builder(MainActivity.this);
        aboutBuilder.setTitle("Top News v1.0");
        aboutBuilder.setMessage("Simple application for displaying Top Headlines from newsapi.org.\n\nIcons made by Freepik from www.flaticon.com.");
        aboutBuilder.setNegativeButton("Close", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int id)
            {
                dialog.dismiss();
            }
        });

        mAbout = aboutBuilder.create();
    }
Теги:
mvvm

2 ответа

0

1- Предоставьте изменяемую LiveData или Observer в вашей ViewModel

public MutableLiveData<Pair<String, String>> countryInfo = new MutableLiveData<>()

2- Передать выбор пользователя в ViewModel

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
   viewModel.countryInfo.setValue(new Pair(countries[position], codes[position]))
   mCountrySelection.dismiss();
}

3- Запустите ваш сценарий использования (бизнес-логику) в вашей ViewModel (загрузка информации на сервер, сохранение в базе данных и т.д.)

4- Обновление View посредством предоставления другого Observable (в этом случае будет работать та же самая countryInfo). В MainActivity наблюдайте countryInfo:

viewmodel.countryInfo.observe(this, new Observer<String>() {
   @Override
   public void onChanged(@Nullable final String newName) {
      // Update the UI
      PreferencesManager.setCountry(countries[position], codes[position]);
      getSupportActionBar().setTitle(PreferencesManager.getCountry());

      getSupportFragmentManager().beginTransaction();
         .replace(R.id.a_main_frame, new ArticlesFragment(), "ArticlesFragment");
         .commit();
   }
});

PS: Лучше всего переместить эту строку во ViewModel, поскольку она содержит часть бизнес-логики:

PreferencesManager.setCountry(countries[position], codes[position]);
  • 0
    Что если я оставлю эту дыру и просто перенесу setCountry во ViewModel? Это считается неправильной практикой MVVM?
  • 0
    Конечно, все зависит от вашей бизнес-логики. Изолировав логику, вы можете получить чистый код, который впоследствии можно будет легко реорганизовать. Для начала просто рефакторинг кода, однако вы считаете целесообразным, так как вы тот, кто лучше всех знает бизнес-логику.
Показать ещё 4 комментария
0

Сделайте 1 интерфейс ItemClick и реализуйте этот интерфейс, откуда вы звоните Dialog.

public interface ItemClick{
public void onClick(int position, String country);
}

Передайте эту ссылку интерфейса на ваш метод диалога

public void createCountriesDialog(ItemClick listner)
    {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
        dialogBuilder.setTitle("Available Countries");

        GridView gridView = new GridView(MainActivity.this);
        final String[] countries = getResources().getStringArray(R.array.countries);
        final String[] codes = getResources().getStringArray(R.array.codes);
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, countries);
        gridView.setAdapter(arrayAdapter);

        dialogBuilder.setView(gridView);
        dialogBuilder.setNegativeButton("Close", new DialogInterface.OnClickListener()
        {
            @Override
            public void onClick(DialogInterface dialog, int which)
            {
                dialog.dismiss();
                listener = null;
            }
        });

        mCountrySelection = dialogBuilder.create();

        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            { 
                listener.onclick(position, countries[position]);
                PreferencesManager.setCountry(countries[position], codes[position]);
                getSupportActionBar().setTitle(PreferencesManager.getCountry());

                FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.a_main_frame, new ArticlesFragment(), "ArticlesFragment");
                fragmentTransaction.commit();

                mCountrySelection.dismiss();
            }
        });
    }

Затем, когда вы щелкаете по элементу сетки, с помощью ссылки на интерфейс вызываете метод onclick Теперь, когда вы получите обратный вызов в onClick (int pos, String country)

Используя вашу модель представления, сделайте вызов API и перезагрузите экран.

Установите listener = null при закрытии диалога, чтобы избежать утечек памяти

  • 0
    Деловая логика должна происходить во ViewModels, но мы не должны также использовать ссылки View на ViewModels.
  • 0
    Да. Вся бизнес-логика должна быть во Viewmodel. Я не передал ни одной ссылки на viewmodel.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню