[英]How to observe Repository LiveData from Fragment via ViewModel
I am having a hard time figuring out how I can connect my Repository
and ViewModel
's live data in-case of @GET
request and observe them in the fragment.我很难弄清楚如何在
@GET
请求的情况下连接我的Repository
和ViewModel
的实时数据并在片段中观察它们。
I don't have this problem when the request type is @POST
because I can use Transformation.switchMap
on the body and whenever the body changes repository's function gets invoked and emits value to the response live data something like this当请求类型为
@POST
时我没有这个问题,因为我可以在主体上使用Transformation.switchMap
并且每当主体更改存储库的 function 被调用并向响应实时数据发出值,如下所示
val matchSetsDetail: LiveData<Resource<MatchDetailBean>> = Transformations.switchMap(matchIdLiveData) { matchId ->
val body = MatchSetRequest(matchId)
repository.getMatchSet(body)
}
but in case of @GET
request, I have several query parameter that my View supplies但是在
@GET
请求的情况下,我的视图提供了几个查询参数
I have this retrofit API call in repository class and the code looks like this我在存储库 class 中有这个 retrofit API 调用,代码看起来像这样
class Repository {
fun checkInCheckOutUser(apiKey: String, userId: Int, status: String, latitude: Double, longitude: Double, checkedOn: Long): LiveData<Resource<BaseResponse>> = liveData {
emit(Resource.Loading())
try {
val response: Response<BaseResponse> = ApiClient.coachApi.checkInCheckOutUser(apiKey, userId, status, latitude, longitude, checkedOn)
if (response.isSuccessful && response.body() != null) {
if (response.body()!!.isValidKey && response.body()!!.success) {
emit(Resource.Success(response.body()!!))
} else {
emit(Resource.Failure(response.body()!!.message))
}
} else {
emit(Resource.Failure())
}
} catch (e: Exception) {
emit(Resource.Failure())
}
}
}
and ViewModel
和
ViewModel
class CheckInMapViewModel : ViewModel() {
val checkInResponse: LiveData<Resource<BaseResponse>> = MutableLiveData()
fun checkInCheckOut(apiKey: String, userId: Int, status: String, latitude: Double, longitude: Double, checkedOn: Long): LiveData<Resource<BaseResponse>> {
return repository.checkInCheckOutUser(apiKey,userId,status,latitude,longitude,checkedOn)
}
}
The main problem is I want to observe checkInResponse
the same way I am observing in case of @POST
request but don't know how to pass observe repository LiveData as I did with my post request above using Transformations.switchMap
.主要问题是我想以与
@POST
请求相同的方式观察checkInResponse
但不知道如何传递观察存储库 LiveData ,就像我使用Transformations.switchMap
对上面的 post 请求所做的那样。 Can anyone help me with this case?谁能帮我处理这个案子?
Edit - Here is my retrofit service class as asked编辑 - 这是我的 retrofit 服务 class
interface CoachApi {
@POST(Urls.CHECK_IN_CHECK_OUT_URL)
suspend fun checkInCheckOutUser(
@Query("apiKey") apiKey: String,
@Query("userId") userId: Int,
@Query("status") status: String,
@Query("latitude") latitude: Double,
@Query("longitude") longitude: Double,
@Query("checkedOn") checkedOn: Long
): Response<SelfCheckResponse>
@POST(Urls.SELF_CHECK_STATUS)
suspend fun getCheckInStatus(
@Query("apiKey") apiKey: String,
@Query("userId") userId: Int
): Response<SelfCheckStatusResponse>
}
The Transformations.switchMap()
just utilizes MediatorLiveData
. Transformations.switchMap()
仅使用MediatorLiveData
。 Since your use-case is a bit different, you could just directly implement it yourself.由于您的用例有点不同,您可以直接自己实现它。
class CheckInMapViewModel : ViewModel() {
private val _checkInResponse = MediatorLiveData<Resource<BaseResponse>>
val checkInResponse: LiveData<Resource<BaseResponse>> = _checkInResponse
fun checkInCheckOut(apiKey: String, userId: Int, status: String, latitude: Double, longitude: Double, checkedOn: Long) {
val data = repository.checkInCheckOutUser(apiKey,userId,status,latitude,longitude,checkedOn)
_checkInResponse.addSource(data) {
if (it is Resource.Success || it is Resource.Failure)
_checkInResponse.removeSource(data)
_checkInResponse.value = it
}
}
}
This code is assuming that data
only emits one terminal element Resource.Success
or Resource.Failure
and cleans up the source with it.此代码假设
data
仅发出一个终端元素Resource.Success
或Resource.Failure
并用它清理源。
Your desirable approach is possible using an intermediate LiveData
which holds the request params, named queryLiveData
.您可以使用包含请求参数的中间
LiveData
来实现您想要的方法,名为queryLiveData
。 When the checkInCheckOut
function is called, we set a new value for it that causes a change in checkInResponse
.当
checkInCheckOut
function 被调用时,我们为其设置了一个新值,导致checkInResponse
发生变化。 Then the change will be transformed into the result of repository.checkInCheckOutUser
using switchMap
.然后使用
switchMap
将更改转换为repository.checkInCheckOutUser
的结果。
CheckInMapViewModel: CheckInMapViewModel:
class CheckInMapViewModel : ViewModel() {
private val queryLiveData = MutableLiveData<CheckInCheckOutParam?>()
init {
queryLiveData.postValue(null)
}
val checkInResponse: LiveData<Resource<BaseResponse>> =
queryLiveData.switchMap { query ->
if(query == null) {
AbsentLiveData.create()
} else {
repository.checkInCheckOutUser(
query.apiKey,
query.userId,
query.status,
query.latitude,
query.longitude,
query.checkedOn
)
}
}
fun checkInCheckOut(
apiKey: String,
userId: Int,
status: String,
latitude: Double,
longitude: Double,
checkedOn: Long
) {
queryLiveData.postValue(
CheckInCheckOutParam(apiKey, userId, status, latitude, longitude, checkedOn)
)
}
private data class CheckInCheckOutParam(
val apiKey: String,
val userId: Int,
val status: String,
val latitude: Double,
val longitude: Double,
val checkedOn: Long
)
}
AbsentLiveData:缺席实时数据:
/**
* A LiveData class that has `null` value.
*/
class AbsentLiveData<T : Any?> private constructor(resource: Resource<T>) :
LiveData<Resource<T>>() {
init {
// use post instead of set since this can be created on any thread
postValue(resource)
}
companion object {
fun <T> create(): LiveData<Resource<T>> {
return AbsentLiveData(Resource.empty())
}
}
}
Try this:尝试这个:
class CheckInMapViewModel : ViewModel() {
private val _checkInResponse: MediatorLiveData<Resource<BaseResponse>> = MediatorLiveData()
val checkInResponse: LiveData<Resource<BaseResponse>>
get() = _checkInResponse
init {
_checkInResponse.addSource(checkInCheckOut()) {
_checkInResponse.value = it
}
}
fun checkInCheckOut(apiKey: String, userId: Int, status: String, latitude: Double, longitude: Double, checkedOn: Long): LiveData<Resource<BaseResponse>> {
return repository.checkInCheckOutUser(apiKey,userId,status,latitude,longitude,checkedOn)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.