我应该在哪里将改造电话放在m​​vvm中并处理其响应

时间:2019-08-08 12:05:28

标签: android mvvm retrofit

我正在尝试研究MVVM模式,不知道在哪里放置改造电话 在MVVM模式中以及如何处理其响应

这是我的loginviewmodel类

public class LoginViewModel extends ViewModel {
    public MutableLiveData<String> email = new MutableLiveData<>();
    public MutableLiveData<String> password = new MutableLiveData<>();
    public MutableLiveData<String> token = new MutableLiveData<>();
    private MutableLiveData<Login> userMutableLiveData;

    public MutableLiveData<Login> getUser() {
        if (userMutableLiveData == null) {
            userMutableLiveData = new MutableLiveData<>();
        }
        return userMutableLiveData;
    }

    public void onClick(View view) {
        Login loginUser = new Login(email.getValue(), password.getValue());
        userMutableLiveData.setValue(loginUser);
            loginAccount(loginUser);
    }

    private void loginAccount(final Login login) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Api.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        Api api = retrofit.create(Api.class);
        Call<Token> call = api.login(new Login(login.getEmail(), login.getPassword()));

        call.enqueue(new Callback<Token>() {
            @Override
            public void onResponse(Call<Token> call, Response<Token> response) {
                //finally we are setting the list to our MutableLiveData
                userMutableLiveData.setValue(new Login(login.getEmail(), login.getPassword(),"Login Successful"));
            }

            @Override
            public void onFailure(Call<Token> call, Throwable t) {
            }
        });
    }
}

这是我在mainactivity中的oncreate

loginViewModel = ViewModelProviders.of(this).get(LoginViewModel.class);

binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
binding.setLifecycleOwner(this);
binding.setLoginViewModel(loginViewModel);

loginViewModel.getUser().observe(this, new Observer<Login>() {
    @Override
    public void onChanged(@Nullable Login loginUser) {
        if (TextUtils.isEmpty(Objects.requireNonNull(loginUser).getEmail())) {
            binding.txtEmailAddress.setError("Enter an E-Mail Address");
            binding.txtEmailAddress.requestFocus();
        } else if (!loginUser.isEmailValid()) {
            binding.txtEmailAddress.setError("Enter a Valid E-mail Address");
            binding.txtEmailAddress.requestFocus();
        } else if (TextUtils.isEmpty(Objects.requireNonNull(loginUser).getPassword())) {
            binding.txtPassword.setError("Enter a Password");
            binding.txtPassword.requestFocus();
        } else if (!loginUser.isPasswordLengthGreaterThan5()) {
            binding.txtPassword.setError("Enter at least 6 Digit password");
            binding.txtPassword.requestFocus();
        } else if (loginUser.getToken().equals("")) {
            Toast.makeText(getApplicationContext(), "Login Failed", Toast.LENGTH_SHORT).show();
        } else {
            binding.tvToken.setText(loginUser.getToken());
        }
    }
});

我的activity_main.xml中也有一个textview,我希望在收到对API调用的响应(无论成功还是失败)之后,将响应发布到textview中。

我想知道这是正确的还是更好的方法?

谢谢!

1 个答案:

答案 0 :(得分:1)

应该为您的应用程序处理业务逻辑的视图模型。最好将您的API调用放在Repository类中,请参见下面的示例:

首先,为整个应用程序创建一个API层

object RestApiHelper {
    private lateinit var retrofit: Retrofit
    private const val CONNECTION_TIME_OUT: Long = 60

    fun getService(): NetworkService {
        retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(getClient())
                .build()
        return retrofit.create(NetworkService::class.java)
    }
}

然后是用于调用API的存储库类

object LoginRepo {
    //Create Retrofit service to hit apis
    private val webService = RestApiHelper.getService()

   // Create function here to login
  fun login(
        successHandler: (Token) -> Unit,
        errorHandler: (ApiError) -> Unit,
        connectionError: (Throwable?) -> Unit,
        request: Login
) {
    webService.login(request).enqueue(object : Callback< Token > {
        override fun onResponse(call: Call< Token >?, response: Response< Token >?) {
            response?.body()?.let {
                // success response
            }
        }

        override fun onFailure(call: Call< Token >?, t: Throwable?) {

        }

    })
}
}

从ViewModel类中,只需调用此仓库

class LoginViewModel : BaseViewModel() {
    var mApiSuccess = MutableLiveData<Token>()

    fun serverLogin(request: Login) {
        LoginRepo.login({
            mApiSuccess.value = it // Lambda function
        }, {
            mApiError.value = it // Lambda function
        }, {
            mConnectionFailure.value = it // Lambda function
        }, request)

    }
}

和BaseViewModel

open class BaseViewModel : ViewModel() {
    var mApiError = MutableLiveData<ApiError>()
    var mConnectionFailure = MutableLiveData<Throwable>()
}

通过这种方式,您只需将关注点分开,ViewModel就会从存储库中查询数据,现在您的存储库将提供您喜欢的源(网络/缓存/文件系统/数据库)中的数据,而您的模型永远都不知道数据源。 现在:

  • 视图:负责UI

  • 模型:业务逻辑

  • 回购:数据提供者