改造协程 livedata 仅在第一次调用
Retroift coroutines livedata called only first time
我是 kotlin 协程的新手。我刚刚创建了用于测试实时数据的新项目,但我无法观察到数据变化。我不明白livedata的概念。什么时候触发?因为当我观察 ROOM 数据库时(不是协程方式。我使用了 MutableLiveData)它工作得很好。每当数据更改时,总是会触发观察者。
我只想编写干净现代的代码。我的期望:当我点击 btnLogin 按钮时(当用户使用另一个帐户登录或者你可以说数据发生变化时)必须触发 livedata。
这是我的例子:
改装界面:
interface RetroMainClient {
@POST("login.php")
suspend fun login(@Body model: UserLoginModel): Response<UserLoginModel>
companion object {
val getApi: RetroMainClient by lazy {
Retrofit.Builder().baseUrl("https://example.com/")
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())).build()
.create(RetroMainClient::class.java)
}
}
}
我的存储库:
class Repository {
suspend fun getLoginApi(model: UserLoginModel) = RetroMainClient.getApi.login(model)
}
我的视图模型:
class MainViewModel : ViewModel() {
fun login(model: UserLoginModel) = liveData(IO) {
try {
emit(Repository().getLoginApi(model))
} catch (e: Exception) {
Log.e("exception", "${e.message}")
}
}
}
和我的 MainActivity:
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
var model = UserLoginModel("user1", "123456")
viewModel.login(model).observe(this, Observer {
if (it.isSuccessful) {
btnLogin.text = it.body()?.username
}
})
btnLogin.setOnClickListener {
model = UserLoginModel("user2", "123456")
CoroutineScope(IO).launch {
try {
Repository().getLoginApi(model)
} catch (e: Exception) {
Log.e("exception:", "${e.message}")
}
}
}
}
}
当您调用 viewModel.login()
方法时,您会创建 LiveData
class 的新实例。为了在每次单击 btnLogin
按钮后在 viewModel.login()
中执行相应的块,您需要为每个 viewModel.login()
调用调用 LiveData.observe()
方法。
在MainActivity
的onCreate
方法中:
btnLogin.setOnClickListener {
model = UserLoginModel("user2", "123456")
viewModel.login(model).observe(this, Observer { data ->
if (it.isSuccessful) {
btnLogin.text = data.body()?.username
}
})
}
另一种方法:
是在MainViewModel
class中启动一个协程并手动更新LiveData
字段:
class MainViewModel : ViewModel() {
val loginResponse: LiveData<Response<UserLoginModel>> = MutableLiveData<Response<UserLoginModel>>()
fun login(model: UserLoginModel) = viewModelScope.launch(IO) {
try {
(loginResponse as MutableLiveData).postValue(Repository().getLoginApi(model))
} catch (e: Exception) {
Log.e("exception", "${e.message}")
}
}
}
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
var model = UserLoginModel("user1", "123456")
viewModel.loginResponse.observe(this, Observer {
if (it.isSuccessful) {
btnLogin.text = it.body()?.username
}
})
btnLogin.setOnClickListener {
model = UserLoginModel("user2", "123456")
viewModel.login(model)
}
}
}
要在 MainViewModel
中使用 viewModelScope
class 添加对 build.gradle 文件的依赖:
final LIFECYCLE_VERSION = "2.2.0-rc03" // add most recent version
api "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION"
我是 kotlin 协程的新手。我刚刚创建了用于测试实时数据的新项目,但我无法观察到数据变化。我不明白livedata的概念。什么时候触发?因为当我观察 ROOM 数据库时(不是协程方式。我使用了 MutableLiveData)它工作得很好。每当数据更改时,总是会触发观察者。
我只想编写干净现代的代码。我的期望:当我点击 btnLogin 按钮时(当用户使用另一个帐户登录或者你可以说数据发生变化时)必须触发 livedata。
这是我的例子:
改装界面:
interface RetroMainClient {
@POST("login.php")
suspend fun login(@Body model: UserLoginModel): Response<UserLoginModel>
companion object {
val getApi: RetroMainClient by lazy {
Retrofit.Builder().baseUrl("https://example.com/")
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())).build()
.create(RetroMainClient::class.java)
}
}
}
我的存储库:
class Repository {
suspend fun getLoginApi(model: UserLoginModel) = RetroMainClient.getApi.login(model)
}
我的视图模型:
class MainViewModel : ViewModel() {
fun login(model: UserLoginModel) = liveData(IO) {
try {
emit(Repository().getLoginApi(model))
} catch (e: Exception) {
Log.e("exception", "${e.message}")
}
}
}
和我的 MainActivity:
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
var model = UserLoginModel("user1", "123456")
viewModel.login(model).observe(this, Observer {
if (it.isSuccessful) {
btnLogin.text = it.body()?.username
}
})
btnLogin.setOnClickListener {
model = UserLoginModel("user2", "123456")
CoroutineScope(IO).launch {
try {
Repository().getLoginApi(model)
} catch (e: Exception) {
Log.e("exception:", "${e.message}")
}
}
}
}
}
当您调用 viewModel.login()
方法时,您会创建 LiveData
class 的新实例。为了在每次单击 btnLogin
按钮后在 viewModel.login()
中执行相应的块,您需要为每个 viewModel.login()
调用调用 LiveData.observe()
方法。
在MainActivity
的onCreate
方法中:
btnLogin.setOnClickListener {
model = UserLoginModel("user2", "123456")
viewModel.login(model).observe(this, Observer { data ->
if (it.isSuccessful) {
btnLogin.text = data.body()?.username
}
})
}
另一种方法:
是在MainViewModel
class中启动一个协程并手动更新LiveData
字段:
class MainViewModel : ViewModel() {
val loginResponse: LiveData<Response<UserLoginModel>> = MutableLiveData<Response<UserLoginModel>>()
fun login(model: UserLoginModel) = viewModelScope.launch(IO) {
try {
(loginResponse as MutableLiveData).postValue(Repository().getLoginApi(model))
} catch (e: Exception) {
Log.e("exception", "${e.message}")
}
}
}
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
var model = UserLoginModel("user1", "123456")
viewModel.loginResponse.observe(this, Observer {
if (it.isSuccessful) {
btnLogin.text = it.body()?.username
}
})
btnLogin.setOnClickListener {
model = UserLoginModel("user2", "123456")
viewModel.login(model)
}
}
}
要在 MainViewModel
中使用 viewModelScope
class 添加对 build.gradle 文件的依赖:
final LIFECYCLE_VERSION = "2.2.0-rc03" // add most recent version
api "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION"