Retrofit 2 return from asynchronous call (call.enqueue())

Viewed 241

My app logs users in to my web server. Android studio created alot of code for the LoginActivity. the flow goes as follows:

from LoginActivity:

loginButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          loadingProgressBar.setVisibility(View.VISIBLE);
          loginViewModel.login(usernameEditText.getText().toString(),
          passwordEditText.getText().toString());
      }
});

Then in LoginViewModel:

    public void login(String username, String password) {
        // can be launched in a separate asynchronous job
        Result<LoggedInUser> result = loginRepository.login(username, password);

        if (result instanceof Result.Success) {
            LoggedInUser data = ((Result.Success<LoggedInUser>) result).getData();
            loginResult.setValue(new LoginResult(new LoggedInUserView(data.getDisplayName())));
        } else {
            loginResult.setValue(new LoginResult(R.string.login_failed));
        }
    }

In LoginRepository

    public Result<LoggedInUser> login(String username, String password) {
        // handle login
        Result<LoggedInUser> result = dataSource.login(username, password);
        if (result instanceof Result.Success) {
            setLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
        }
        return result;
    }

Finally LoginDataSource

    public Result<LoggedInUser> login(String username, String password) {

        try {
            LoggedInUser fakeUser = new LoggedInUser();
            Call<String> call = serverApi.authenticate(username, password);
            call.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    if (response.code() == 200) {
                        fakeUser.setDisplayName(username);
                        fakeUser.setUserId("user id");
                    }
                    System.out.println(response.code());
                }

                @Override
                public void onFailure(Call<String> call, Throwable t) {
                }
            });
            // TODO: handle loggedInUser authentication
            if (fakeUser.getDisplayName() == null) {
                throw new Exception("could not login!");
            }
            return new Result.Success<>(fakeUser);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result.Error(new IOException("Error logging in", e));
        }
    }

I know I can put the onClick() method from LoginActivity in an AsyncTask and then call call.execute() in LoginDataSource. Is that option just plain better/more standard/more convenient or should I preferably use call.enqueue()? How do I return a Result.? object from the login() method based on the response I get from call.enqueue()? Now obviously the code just passes through and returns the empty fakeUser.

And what does the comment mean in LoginViewModel : // can be launched in a separate asynchronous job? Does it mean the method call to LoginViewModel.login() or the method call to LoginRepository.login()?

0 Answers
Related