я должен всегда вызывать мой метод в viewmodel из фрагмента / деятельности? - PullRequest
0 голосов
/ 17 марта 2020

, поэтому я новичок в шаблоне MVVM в Android. Я хочу выполнить два действия: когда нажата кнопка, затем сначала я проверяю соединение inte rnet, если соединение inte rnet доступно, затем выполняю вход на сервер.

вот мой ViewModel

class LoginViewModel(application: Application) : AndroidViewModel(application) {


    private val _hasInternetConnection = MutableLiveData(false)
    val hasInternetConnection: LiveData<Boolean>
        get() = _hasInternetConnection


    fun checkIfItHasInternetConnection() {

        if (InternetConnection.checkConnection(getApplication())) {
            _hasInternetConnection.value = true
        } else {
            _hasInternetConnection.value = false

        }

    }

    fun performLogin() {

    }



}

и вот мой фрагмент

class LoginFragment : Fragment() {

    lateinit var model: LoginViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        model = ViewModelProvider(this).get(LoginViewModel::class.java)

        button.setOnClickListener {
            model.checkIfItHasInternetConnection()
        }

        model.hasInternetConnection.observe(this, Observer { hasInternetConnection ->

            if (!hasInternetConnection) {
                longToast("You have no internet connection")
            } else {

            }

        })



    }


}

Проблема в том, что я не уверен, где мне нужно вызывать метод performLogin из моей модели представления, нужно ли мне вызывать его в мой фрагмент подобен этому в наблюдателе?

model.hasInternetConnection.observe(this, Observer { hasInternetConnection ->

            if (!hasInternetConnection) {
                longToast("You have no internet connection")
            } else {
                model.performLogin()
            }

 })

или мне нужно вызывать его внутри самой модели представления после выполнения проверки соединения inte rnet? вот так

// inside viewModel
fun checkIfItHasInternetConnection() {

        if (InternetConnection.checkConnection(getApplication())) {
            _hasInternetConnection.value = true
            performLogin()
        } else {
            _hasInternetConnection.value = false

        }

    }

извините, если вопрос слишком базовый c, я пытаюсь выучить MVVM, и из руководств, которые я смотрю, кажется, что мне нужно вызвать метод в viewModel из фрагмента, но будет удобнее, если я позвоню из самой модели представления. Мне нужно знать, как правильно решить дело, как это

Ответы [ 2 ]

0 голосов
/ 17 марта 2020

Предлагаю вам взглянуть на Android Руководство разработчика по архитектуре приложений . Он основан на архитектуре MVVM и представляет репозиторий, который обрабатывает веб-вызовы. Может быть, это вам поможет.

Но чтобы ответить на ваш вопрос: следуя четкой архитектуре MVVM, Activity должен вызывать только метод в ViewModel, а не делать какие-либо логики c. Этот метод во ViewModel должен либо выполнить logi c, либо делегировать его дальше в Model или, например, в репозиторий.

Если вход в систему не может быть выполнен из-за отсутствия соединения Inte rnet, ViewModel должен обработать это, установив некоторые LiveData, возможно, LiveData<String> errorMessage, и Activity должен наблюдать эти LiveData и показывать сообщение пользователь всякий раз, когда этот LiveData предоставляет новую строку.

Редактировать: пример кода.

Репозиторий:

public void performLogin(String username, String password, MutableLiveData<LoginStatus> loginStatus) {
  if (/*check Internet access*/) {
    performLoginAsync(username, password, loginStatus);
  } else {
    loginStatus.setValue(LoginStatus.NO_INTERNET);
  }
}
private void performLoginAsync(String username, String password, MutableLiveData<LoginStatus> loginStatus) {
  /*perform async login with success and error callback*/
  myWebservice.login(
    username,
    password,
    () -> loginStatus.setValue(LoginStatus.SUCCESS), /*success callback*/
    error -> loginStatus.setValue(LoginStatus.ERROR) /*error callback*/
  );
}

ViewModel:

public MutableLiveData<LoginStatus> loginStatus;
private Repository myRepository;
public void performLogin(String username, String password) {
  myRepository.performLogin(username, password, loginStatus);
}

Фрагмент:

private ViewModel myViewModel;
private EditText loginUsername, loginPassword;
private Button loginButton;

/* in some method, where you want your initialization, e.g. in onViewCreated */
  loginButton.setOnClickListener(v -> {
    myViewModel.login(loginUsername.getText().toString(), loginPassword.getText().toString());
  });
  myViewModel.loginStatus.observe(this, loginStatus -> Toast.makeText(this, loginStatus.getText(), Toast.LENGTH_LONG));

Этот код не является рабочим примером, но он должен содержать большую его часть и указывать правильное направление. Надеюсь, поможет. Если что-то не понятно, сделайте еще один комментарий

0 голосов
/ 17 марта 2020

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

...