user login using viewmodel and retrofit

前端 未结 3 1268
Happy的楠姐
Happy的楠姐 2020-12-06 08:58

im trying to do login using retrofit and viewmodel

i have done successfully login with only retrofit...referred this tutorial--> https://www.youtube.com/watch?v=j0

3条回答
  •  长情又很酷
    2020-12-06 09:22

    class LoginActivity : BaseClassActivity() {
        private val viewModel by viewModels()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.login_activity)
    
            val button = findViewById(R.id.plusbutton)
            val forgotpassword = findViewById(R.id.forgotpassword)
    
            button.setOnClickListener {
                val i = Intent(applicationContext, RegisterActivity::class.java)
                startActivity(i)
            }
    
            forgotpassword.setOnClickListener {
                val i = Intent(applicationContext, ForgotPassword::class.java)
                startActivity(i)
            }
    
            loginuser.onTextChanged {
                viewModel.user.value = it.toString()
            }
    
            loginpassword.onTextChanged {
                viewModel.password.value = it.toString()
            }
    
            loginbtn.setOnClickListener {
                viewModel.login()
            }
    
            viewModel.loginResult.observe(this) { result ->
                when (result) {
                    UserMissing -> {
                        Toast.makeText(
                            applicationContext, "Data is missing", Toast.LENGTH_LONG
                        ).show()
                        loginuser.error = "Email required"
                        loginuser.requestFocus()
                    }
                    PasswordMissing -> {
                        loginpassword.error = "Password required"
                        loginpassword.requestFocus()
                    }
                    NetworkFailure -> {
                    }
                    NetworkError -> {
                        showToast(applicationContext, result.userMessage)
                    }
                    Success -> {
                        val intent = Intent(applicationContext, HomeActivity::class.java)
                        intent.flags =
                            Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
                        showToast(applicationContext, res.body()?.message)
                        Log.d("kjsfgxhufb", response.body()?.status.toString())
                        startActivity(intent)
                        finish()
                    }
                }.safe()
            }
        }
    }
    
    class LoginViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
        sealed class LoginResult {
            object UserMissing : LoginResult(),
    
            object PasswordMissing : LoginResult(),
    
            class NetworkError(val userMessage: String) : LoginResult(),
    
            object NetworkFailure : LoginResult(),
    
            object Success : LoginResult()
        }
    
        val user: MutableLiveData = savedStateHandle.getLiveData("user", "")
        val password: MutableLiveData = savedStateHandle.getLiveData("password", "")
    
        private val loginResultEmitter = EventEmitter()
        val loginResult: EventSource = loginResultEmitter
    
        fun login() {
            val email = user.value!!.toString().trim()
            val password = password.value!!.toString().trim()
    
            if (email.isEmpty()) {
                loginResultEmitter.emit(LoginResult.UserMissing)
                return
            }
    
    
            if (password.isEmpty()) {
                loginResultEmitter.emit(LoginResult.PasswordMissing)
                return
            }
    
            RetrofitClient.instance.userLogin(email, password)
                .enqueue(object : Callback {
                    override fun onFailure(call: Call, t: Throwable) {
                        Log.d("res", "" + t)
                        loginResultEmitter.emit(LoginResult.NetworkFailure)
                    }
    
                    override fun onResponse(
                        call: Call,
                        response: Response
                    ) {
                        var res = response
    
                        Log.d("response check ", "" + response.body()?.status.toString())
                        if (res.body()?.status == 200) {
                            SharedPrefManager.getInstance(applicationContext).saveUser(response.body()?.data!!)
                            loginResultEmitter.emit(LoginResult.Success)
                        } else {
                            try {
                                val jObjError =
                                    JSONObject(response.errorBody()!!.string())
                                loginResultEmitter.emit(LoginResult.NetworkError(jObjError.getString("user_msg")))
                            } catch (e: Exception) {
                                // showToast(applicationContext,e.message) // TODO
                                Log.e("errorrr", e.message)
                            }
                        }
                    }
                })
        }
    }
    

    Using

    allprojects {
        repositories {
            // ...
            maven { url "https://jitpack.io" }
        }
        // ...
    }
    
    implementation 'com.github.Zhuinden:live-event:1.1.0'
    

    EDIT: some missing blocks to actually make this compile:

    fun  T.safe(): T = this // helper method
    

    These dependencies in Gradle

    implementation "androidx.core:core-ktx:1.3.2"
    implementation "androidx.activity:activity-ktx:1.1.0"
    implementation "androidx.fragment:fragment-ktx:1.2.5"
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0"
    

    Also add

    android {
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
    
      kotlinOptions {
        jvmTarget = "1.8"
      }
    }
    

    To access applicationContext in ViewModel, you'll need to use AndroidViewModel instead of ViewModel

    class LoginViewModel(
        private val application: Application,
        private val savedStateHandle: SavedStateHandle
    ): AndroidViewModel(application) {
        private val applicationContext = application
    

    And that should fix it

    EDIT: apparently the "onTextChanged" is doAfterTextChanged in ktx, what I use is this:

    inline fun EditText.onTextChanged(crossinline textChangeListener: (String) -> Unit) {
        addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(editable: Editable) {
                textChangeListener(editable.toString())
            }
    
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
            }
    
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            }
        })
    }
    

提交回复
热议问题