我正在尝试使用改造和 View 模型进行登录
我只用改造就成功登录了...引用本教程--> https://www.youtube.com/watch?v=j0wH0m_xYLs
我还没有找到任何与使用 View 模型登录相关的教程
找到了这个 stackoverflow 问题,但仍然没有答案 --> How to make retrofit API call request method post using LiveData and ViewModel
这是我的通话 Activity :--
class LoginActivity : BaseClassActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.login_activity)
val button = findViewById<ImageView>(R.id.plusbutton)
val forgotpassword=findViewById<TextView>(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)
}
loginbtn.setOnClickListener {
val email = loginuser.text.toString().trim()
val password = loginpassword.text.toString().trim()
if (email.isEmpty()) {
Toast.makeText(
applicationContext, "Data is missing",Toast.LENGTH_LONG
).show()
loginuser.error = "Email required"
loginuser.requestFocus()
return@setOnClickListener
}
if (password.isEmpty()) {
loginpassword.error = "Password required"
loginpassword.requestFocus()
return@setOnClickListener
}
RetrofitClient.instance.userLogin(email, password)
.enqueue(object : Callback<LoginResponse> {
override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
Log.d("res", "" + t)
}
override fun onResponse(
call: Call<LoginResponse>,
response: Response<LoginResponse>
) {
var res = response
Log.d("response check ", "" + response.body()?.status.toString())
if (res.body()?.status==200) {
SharedPrefManager.getInstance(applicationContext)
.saveUser(response.body()?.data!!)
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()
}
else
{
try {
val jObjError =
JSONObject(response.errorBody()!!.string())
showToast(applicationContext,jObjError.getString("user_msg"))
} catch (e: Exception) {
showToast(applicationContext,e.message)
Log.e("errorrr",e.message)
}
}
}
})
}
}}
以下是登录响应:-
data class LoginResponse(val status: Int, val data: Data, val message: String, val user_msg:String)
数据类:-
data class Data(
@SerializedName("id") val id: Int,
@SerializedName("role_id") val role_id: Int,
@SerializedName("first_name") val first_name: String?,
@SerializedName("last_name") val last_name: String?,
@SerializedName("email") val email: String?,
@SerializedName("username") val username: String?,
@SerializedName("profile_pic") val profile_pic: String?,
@SerializedName("country_id") val country_id: String?,
@SerializedName("gender") val gender: String?,
@SerializedName("phone_no") val phone_no: String,
@SerializedName("dob") val dob: String?,
@SerializedName("is_active") val is_active: Boolean,
@SerializedName("created") val created: String?,
@SerializedName("modified") val modified: String?,
@SerializedName("access_token") val access_token: String?
)
确实需要与登录 View 模型相关的帮助
提前致谢
添加epicpandaforce答案时遇到的错误:--
在登录 View 模型中:--
在登录 Activity 中:- 1-->
2-->
3-->
最佳答案
class LoginActivity : BaseClassActivity() {
private val viewModel by viewModels<LoginViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.login_activity)
val button = findViewById<ImageView>(R.id.plusbutton)
val forgotpassword = findViewById<TextView>(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<String> = savedStateHandle.getLiveData("user", "")
val password: MutableLiveData<String> = savedStateHandle.getLiveData("password", "")
private val loginResultEmitter = EventEmitter<LoginResult>()
val loginResult: EventSource<LoginResult> = 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<LoginResponse> {
override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
Log.d("res", "" + t)
loginResultEmitter.emit(LoginResult.NetworkFailure)
}
override fun onResponse(
call: Call<LoginResponse>,
response: Response<LoginResponse>
) {
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)
}
}
}
})
}
}
使用这个库(我写这个库是因为没有任何其他库可以在不使用 SingleLiveEvent 的反模式或事件包装器的情况下正确解决这个问题)
allprojects {
repositories {
// ...
maven { url "https://jitpack.io" }
}
// ...
}
implementation 'com.github.Zhuinden:live-event:1.1.0'
编辑:一些缺失的 block 来实际编译:
fun <T> T.safe(): T = this // helper method
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"
同时添加
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
要在 ViewModel
中访问 applicationContext
,您需要使用 AndroidViewModel
而不是 ViewModel
class LoginViewModel(
private val application: Application,
private val savedStateHandle: SavedStateHandle
): AndroidViewModel(application) {
private val applicationContext = application
这应该可以解决它
编辑:显然“onTextChanged”是ktx中的doAfterTextChanged
,我使用的是这个:
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) {
}
})
}
关于android - 使用 View 模型和改造的用户登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64352752/