问题: 该代码仅在我刚启动应用程序或打开屏幕时才有效(据我了解,更改配置后,活动将再次绑定)。
然后我尝试发出请求,但对我来说不起作用。 在尽可能挂起Log之后,我意识到该代码未在resultLiveData的liveData()内部执行。 为什么会这样呢?以及如何解决?
有一个BaseRemoteSource负责从远程服务获取数据
abstract class BaseDataSource{
public suspend fun <T> getResult(call : suspend () -> Response<T>) : Result<T>{
try {
//Получаем ответ от вызова
val response = call()
if(response.isSuccessful) {
//тело
val body = response.body()
if (body != null) return Result.success(body)
}
return error("${response.code()} ${response.message()} ${response.errorBody()}")
}
catch (e: Exception){
Log.d("BaseDataSource", e.toString())
return Result.error(e.message ?: e.toString())
}
}
}
有一个继承人
class AlbumRemoteDataSource @Inject constructor(
private val apiService: APIService
): BaseDataSource(){
suspend fun getAlbumsBySearch(searchQuery: String): Result<AlbumsResponse>{
val result = getResult{apiService.getAlbumsBySearch(searchQuery)}
Log.d("AlbumRemoteDataSource", result.toString())
return result
}
}
在存储库中,我从远程服务获取数据,将其添加到数据库中,然后从中获取现成的数据集。
class AlbumRepository @Inject constructor(private val remoteSource: AlbumRemoteDataSource, private val database: AppDatabase){
fun getAlbumsBySearch(searchQuery: String): LiveData<Result<List<Album>>>{
Log.d("RepositoryNew", searchQuery)
val resultLiveData = resultLiveData(
databaseQuery = {database.getAlbumDao().getAlbumsBySearch("%${searchQuery}%")},
networkCall = {remoteSource.getAlbumsBySearch(searchQuery)},
saveCallResult = {database.getAlbumDao().insertAll(it.results)}
)
Log.d("AlbumRepository", resultLiveData.value.toString())
return resultLiveData
}
}
为此,我编写了resultLiveData
fun <T, A> resultLiveData(
databaseQuery: () -> LiveData<T>,
networkCall: suspend () -> Result<A>,
saveCallResult: suspend (A) -> Unit): LiveData<Result<T>>{
Log.d("resultLiveData", "input")
val news = liveData(Dispatchers.IO){
emit(Result.loading<T>())
val responseSource = networkCall.invoke()
Log.d("ResultLiveData Network", responseSource.toString())
if(responseSource.status == Result.Status.SUCCESS) {
saveCallResult(responseSource.data!!)
Log.d("resultLiveData", "save database")
}
else if(responseSource.status == Result.Status.ERROR){
emit(Result.error(responseSource.error))
Log.d("resultLiveData", "error ${responseSource.error}")
}
val databaseSource = databaseQuery.invoke()
Log.d("ResultLiveData Database", databaseSource.value.toString())
emitSource(databaseSource.map { Result.success(it) })
}
Log.d("resultLiveDataAll", news.toString())
return news
}
我想通过SearchView获取新数据。为此,我在ViewModel中调用hangleSearchQuery方法
private fun getAlbumsBySearch(searchQuery: String) = repository.getAlbumsBySearch(searchQuery)
fun handleSearchQuery(text: String?) {
albums = getAlbumsBySearch(text.toString())
}
如果您查看日志,那么为什么它出现在resultLiveData中,而不进入liveData part()
日志
2020-02-04 19:18:06.522 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumListViewModel SV: ryf
2020-02-04 19:18:06.964 5326-5326/ru.ddstudio.simpleitunesapp D/RepositoryNew: ryfh
2020-02-04 19:18:06.964 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveData: input
2020-02-04 19:18:06.965 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveDataAll: androidx.lifecycle.CoroutineLiveData@f0a4b27
2020-02-04 19:18:06.965 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumRepository: null
2020-02-04 19:18:06.965 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumListViewModel SV: ryfh
2020-02-04 19:18:07.174 5326-5326/ru.ddstudio.simpleitunesapp D/RepositoryNew: ryfhh
2020-02-04 19:18:07.175 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveData: input
2020-02-04 19:18:07.175 5326-5326/ru.ddstudio.simpleitunesapp D/resultLiveDataAll: androidx.lifecycle.CoroutineLiveData@17211d4
2020-02-04 19:18:07.175 5326-5326/ru.ddstudio.simpleitunesapp D/AlbumRepository: null
ViewModel
class AlbumListViewModel @Inject constructor(private val repository: AlbumRepository): ViewModel(){
private var albums : LiveData<Result<List<Album>>> = getAlbumsBySearch("")
private fun getAlbumsBySearch(searchQuery: String): LiveData<Result<List<Album>>>{
return repository.getAlbumsBySearch(searchQuery)}
fun getAlbums(): LiveData<Result<List<Album>>>{
Log.d("AlbumListViewModel", albums.value.toString())
return albums
}
fun handleSearchQuery(text: String?) {
albums = if (text != null){
getAlbumsBySearch(text)
} else{
getAlbumsBySearch("")
}
Log.d("AlbumListViewModel SV", text.toString())
}