问题描述
我有一个实体“drinks”,它有 [id;name;thumb] 并且我正在使用这些实体进行 2 次响应调用。一个响应返回给我一个 NonAlcohol 饮料列表,另一个AlcoholList,我使用 Room 来缓存数据。但是当我运行应用程序时,我看到我的列表合并了,经过一番思考,我找到了解决这个问题的方法,我在我的实体“alcoholStatus”中添加了一个布尔字段。 但是我无法理解如何将数据设置为此变量正确使用此 AccessDataStrategy。我是 Android 新手,这是我的学习项目。请告诉我如何解决这个问题的正确方法。
https://github.com/YaroslavSulyma/LetsDrink/tree/master/app/src/main/java/com/example/letsdrink
非常感谢!
实体
@Entity(tableName = "drinks")
data class DrinksModel(
@Serializedname("strDrink")
val strDrink: String,@Serializedname("strDrinkThumb")
val strDrinkThumb: String?,@Serializedname("idDrink")
@PrimaryKey
val idDrink: Int,var alcohol: Boolean
)
数据访问策略代码
fun <T,A> performGetoperation(
databaseQuery: () -> LiveData<T>,networkCall: suspend () -> Resource<A>,saveCallResult: suspend (A) -> Unit
): LiveData<Resource<T>> =
liveData(dispatchers.IO) {
emit(Resource.loading())
val source = databaseQuery.invoke().map { Resource.success(it) }
emitSource(source)
val responseStatus = networkCall.invoke()
if (responseStatus.status == SUCCESS) {
saveCallResult(responseStatus.data!!)
} else if (responseStatus.status == ERROR) {
emit(Resource.error(responseStatus.message!!))
emitSource(source)
}
}
资源
data class Resource<out T>(val status: Status,val data: T?,val message: String?) {
enum class Status {
SUCCESS,ERROR,LOADING
}
companion object {
fun <T> success(data: T): Resource<T> {
return Resource(Status.SUCCESS,data,null)
}
fun <T> error(message: String,data: T? = null): Resource<T> {
return Resource(Status.ERROR,message)
}
fun <T> loading(data: T? = null): Resource<T> {
return Resource(Status.LOADING,null)
}
}
}
存储库
class CocktailsRepository @Inject constructor(
private val remoteDataSource: CocktailsRemoteDataSource,private val localDataSource: CocktailsDao
) {
fun getAlcoholicCocktails() = performGetoperation(
databaseQuery = { localDataSource.getAlcoholicCocktails() },networkCall = { remoteDataSource.getAllAlcoholicCocktails()},saveCallResult = { localDataSource.insertAllDrinks(it.drinks) }
)
fun getNonAlcoholicCocktails() = performGetoperation(
databaseQuery = { localDataSource.getNonAlcoholicCocktails() },networkCall = { remoteDataSource.getAllNonAlcoholicCocktails() },saveCallResult = { localDataSource.insertAllDrinks(it.drinks) }
)
}
DAO
@Dao
interface CocktailsDao {
@Query("SELECT * FROM drinks WHERE alcohol = 'true'")
fun getAlcoholicCocktails(): LiveData<List<DrinksModel>>
@Query("SELECT * FROM drinks WHERE alcohol = 'false'")
fun getNonAlcoholicCocktails(): LiveData<List<DrinksModel>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAllDrinks(drinks: List<DrinksModel>)
}
远程数据源
class CocktailsRemoteDataSource @Inject constructor(private val iCocktailApisService: ICocktailApisService) :
BaseDataSource() {
suspend fun getAllAlcoholicCocktails() =
getResult { iCocktailApisService.allAlcoholicAndNonAlcoholicCocktails("Alcoholic") }
suspend fun getAllNonAlcoholicCocktails() =
getResult { iCocktailApisService.allAlcoholicAndNonAlcoholicCocktails("Non_Alcoholic") }
}
解决方法
首先:我强烈建议您为远程和本地模型类定义单独的数据类,并在需要时在它们之间进行映射,例如:
远程数据模型:
data class DrinkRemoteModel(
@SerializedName("idDrink")
val idDrink: Int,@SerializedName("strDrink")
val strDrink: String,@SerializedName("strDrinkThumb")
val strDrinkThumb: String?,@SerializedName("alcohol")
var alcohol: Boolean
)
本地数据模型:
@Entity(tableName = "drinks")
data class DrinkLocalModel(
@PrimaryKey
@ColumnInfo(name = "idDrink")
val idDrink: Int,@ColumnInfo(name = "strDrink")
val strDrink: String,@ColumnInfo(name = "strDrinkThumb")
val strDrinkThumb: String?,@ColumnInfo(name = "alcohol")
var alcohol: Boolean
)
回到您的实现:我认为导致问题的原因是 Room 将实体中的布尔字段映射到整数列,1
用于 {{ 1}} 和 true
用于 0
,因此请尝试更改您在 DAO 中的查询,如下所示:
false
或者:您可以用一个 DAO 函数替换 @Dao
interface CocktailsDao {
@Query("SELECT * FROM drinks WHERE alcohol = 1")
fun getAlcoholicCocktails(): LiveData<List<DrinksModel>>
@Query("SELECT * FROM drinks WHERE alcohol = 0")
fun getNonAlcoholicCocktails(): LiveData<List<DrinksModel>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAllDrinks(drinks: List<DrinksModel>)
}
和 getAlcoholicCocktails
,如下所示:
getNonAlcoholicCocktails