1

嗨,我还有LoginActivity一些LoginViewModel课程。我有 showLoadinghideLoading所以BaseActivity可以从每个活动中访问它。

我可以调用类似LoginActivity的方法LoginViewModelmNavigator?.startForgotPasswordActivity()

我想从那时起调用它,LoginViewModel然后使用 MVVM 怎么做呢?或者我会采用错误的方法。请建议这样做的正确方法是什么?

基本活动.kt

abstract class BaseActivity : AppCompatActivity(), AnkoLogger {

    private val progressBar: ProgressBar? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    protected fun getToolbar(): Toolbar {
        val toolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar)
        return toolbar
    }

    protected fun performDependencyInjection() {
        AndroidInjection.inject(this);
    }

    @TargetApi(Build.VERSION_CODES.M)
    fun requestPermissionsSafely(permissions: Array<String>, requestCode: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissions, requestCode)
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    fun hasPermission(permission: String): Boolean {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED
    }

    fun isNetworkConnected(): Boolean {
        return NetworkUtils.isNetworkConnected(applicationContext)
    }

    fun showLoading() {
        hideLoading()
        // show progress bar
    }

    fun hideLoading() {
        // hide progress bar
    }

}

登录活动.kt

class LoginActivity : BaseActivity(), LoginNavigator {

    @Inject
    lateinit var loginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        performDependencyInjection()
        super.onCreate(savedInstanceState)
        val activityLoginBinding: ActivityLoginBinding = DataBindingUtil.setContentView<ActivityLoginBinding>(this, R.layout.activity_login)
        activityLoginBinding.loginViewModel = loginViewModel
        loginViewModel.mNavigator = this
    }

    override fun startHomeActivity() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun startRegistrationActivity() {
        startActivity(Intent(this, RegistrationActivity::class.java))
    }

    override fun startForgotPasswordActivity() {
        startActivity(Intent(this, ForgotPasswordActivity::class.java))
    }

    override fun handleError(throwable: Throwable) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

登录视图模型.kt

class LoginViewModel : BaseViewModel<LoginNavigator>(), AnkoLogger {

    val emailField = ObservableField<String>()

    private val email: String
        get() = emailField.get()

    val passwordField = ObservableField<String>()

    private val password: String
        get() = passwordField.get()

    @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
    fun login(view: View) {
        if (isEmailAndPasswordValid(email, password)) {
            ApiHelperImpl().doServerLoginApiCall(email, password)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribeWith(object : CallbackWrapper<LoginResponse>() {

                        override fun onSuccess(loginResponse: LoginResponse) {
                            info { loginResponse }
                        }
                    })
        }
    }

    /**
     * Validate email and password. It checks email and password is empty or not
     * and validate email address is correct or not
     * @param email email address for login
     * @param password password for login
     * @return true if email and password pass all conditions else false
     */
    private fun isEmailAndPasswordValid(email: String, password: String): Boolean {

        if (email.isEmpty()) return false

        if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) return false

        if (password.isEmpty()) return false

        return true
    }

}

BaseViewModel.kt

abstract class BaseViewModel<N> {
    var mNavigator: N? = null
}
4

1 回答 1

1

可以有两种相同的方法

1) 根据 mvp 和 viewmodel 使用所有与 UI 更新或 UI 事件侦听器相关的功能,仅尝试管理 api 和其他逻辑等数据

class LoginActivity : BaseActivity(), LoginNavigator {

    @Inject
    lateinit var mLoginViewModel: LoginViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        mLoginViewModel.mNavigator = this

        callApi()
    }

    private fun callApi() {
        showLoading()
        mLoginViewModel.callApi()
    }

    override fun openHomeScreen(model: Model) {
        hideLoading()
        showSnackBar(constraint_root, model.Domain)
    }

}


class LoginViewModel(sessionManager: SessionManager, requestInterface: RequestInterface) : BaseViewModel<LoginNavigator>(sessionManager, requestInterface) {

    fun callApi() {
        requestInterface.getServiceIP()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(this::handleResponse, this::handleError)
    }

    private fun handleResponse(model: Model) {
        if (model.Domain == null) {
            mNavigator!!.openHomeScreen(model)
        } else {

        }
    }

    private fun handleError(error: Throwable) {
        error.printStackTrace()
    }
}

2) 在登录界面添加一个功能

interface LoginNavigator {
    fun openHomeScreen()
    fun getActivity(): BaseActivity
}

在 LoginActivity 中重写该函数并返回

override fun getActivity(): BaseActivity = this

现在使用导航器,您可以访问基本活动并调用显示/隐藏加载程序功能

mNavigator!!.getActivity().showLoading()
于 2018-03-30T08:52:49.257 回答