如何在模型中设置数据?

How to set data in Model?

我有一个具有 [id;name;thumb] 的实体“饮料”,我正在使用这些实体进行 2 次响应调用。一个响应 returns 给我一个非酒精饮料清单,另一个 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
)

DataAccessStrategyCode

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, data, message)
        }

        fun <T> loading(data: T? = null): Resource<T> {
            return Resource(Status.LOADING, data, 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 对应 true0 对应 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>)
}

或者: 你可以用一个 DAO 函数替换你的 getAlcoholicCocktailsgetNonAlcoholicCocktails,像这样:

@Query("SELECT * FROM drinks WHERE alcohol = :isAlcoholic")
fun getCocktails(isAlcoholic : Boolean = true): LiveData<List<DrinksModel>>