【问题标题】:LiveData not updating after inserting into Room databaseLiveData 插入 Room 数据库后未更新
【发布时间】:2019-04-29 10:34:04
【问题描述】:

我的项目基本上允许用户创建一个产品列表,其中可以添加不同的产品。所以在我的例子中,我的实体之间存在的关系是多对多的:我有一个表,用于在安装应用程序时添加的所有产品,我有一个包含用户创建列表的表,最后我有一个表用户将产品添加到列表时的记录。

我遇到的问题是,在用户将产品添加到列表后,活动中观察到的 LiveData 不会更新列表,我无法弄清楚原因。

活动(产品代码是用户在另一个活动中引入的结果):

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_list_of_products)

        // Get the listname from the bundle
        listName = intent.extras.getString(resources.getString(R.string.INTENT_EXTRA_LISTNAME))

        // Set up the ViewModel
        viewModel = ViewModelProviders.of(this, ListOfProductsViewModelFactory(application, listName)).get(ListOfProductsViewModel::class.java)

        // RecyclerView setup
        val recyclerView = findViewById<RecyclerView>(R.id.productRecyclerView)
        val mAdapter = ProductAdapter(this)
        recyclerView.adapter = mAdapter
        recyclerView.layoutManager = LinearLayoutManager(this)
        viewModel!!.getProductsInProductList().observe(this, Observer {
            products -> mAdapter.setProducts(products!!)
        })
    }

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if(requestCode == NEW_PRODUCT_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            val code = data!!.extras.getString(resources.getString(R.string.ADD_MANUALLY_ACTIVITY_REPLY))
            val resultOfInsertion = viewModel!!.insertProductInProductList(code)
            if(resultOfInsertion) {
                Toast.makeText(applicationContext, "${code} successful added",
                    Toast.LENGTH_LONG).show()
            } else {
                Toast.makeText(applicationContext, "${code} was not added",
                    Toast.LENGTH_LONG).show()
            }
        }

        else {
            Toast.makeText(applicationContext, "Insertion cancelled",
                Toast.LENGTH_LONG).show()
        }
    }

视图模型:

private var mRepo = ProductsInProductListRepository(application, listName)
    private val productsInProductList = mRepo.getProductsInProductList()

    fun getProductsInProductList() : LiveData<List<Product>> {
        return productsInProductList
    }

    fun insertProductInProductList(code: String) : Boolean {
        return mRepo.insertProductInProductList(code)
    }

存储库:

private var productsInProductListDao : ProductsInProductListDao
    private var productsInProductList : LiveData<List<Product>>
    private val listName : String

    constructor(application : Application, listName: String) {
        val db = ProductDatabase.getProductDatabase(application)
        this.productsInProductListDao = db!!.productsInProductListDao()
        this.listName = listName
        this.productsInProductList = productsInProductListDao.getProducstForProductList(listName)
    }

    fun getProductsInProductList() : LiveData<List<Product>> {
        return productsInProductList
    }

    fun insertProductInProductList(productCode : String) : Boolean {
        if(isProductAlreadyAdded(productCode)) {
            return false
        }
        InsertProductInProductListAsync(productsInProductListDao, listName).execute(productCode)
        return true
    }

    private fun isProductAlreadyAdded(productCode : String): Boolean {
        return productsInProductListDao.getProductAddedToCertainList(listName, productCode).isNotEmpty()
    }

DAO:

@Dao
interface ProductsInProductListDao {

    @Insert(onConflict = OnConflictStrategy.FAIL)
    fun insertProductInProductList(productInProductList: ProductsInProductList)

    @Query("SELECT code, model, pvpr, qtr, segmentation FROM product_table INNER JOIN products_in_productlist_table ON code=productCode WHERE listName=:listName")
    fun getProducstForProductList(listName : String) : LiveData<List<Product>>

    @Query("SELECT code, model, pvpr, qtr, segmentation FROM product_table INNER JOIN products_in_productlist_table ON code=productCode WHERE listName=:listName and code=:productCode")
    fun getProductAddedToCertainList(listName : String, productCode: String) : List<Product>
}

实体:

@Entity(
    indices = [Index("productCode")],
    tableName = "products_in_productlist_table",
    primaryKeys = ["listName", "productCode"],
    foreignKeys = [
        ForeignKey( onDelete = ForeignKey.CASCADE,
            entity = ProductList::class,
            parentColumns = ["name"],
            childColumns = ["listName"]),
        ForeignKey( entity = Product::class,
            parentColumns = ["code"],
            childColumns = ["productCode"])
    ]

)
class ProductsInProductList {

    @NonNull
    @ColumnInfo(name = "listName")
    val listName : String

    @NonNull
    @ColumnInfo(name = "productCode")
    val productCode : String

    constructor(listName: String, productCode: String) {
        this.listName = listName
        this.productCode = productCode
    }
}

产品适配器:

private val mInflater = LayoutInflater.from(context)
    private val context = context
    private var mProducts : List<Product>? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
        val itemView = mInflater.inflate(R.layout.product_item, parent, false)
        return ProductViewHolder(itemView)
    }

    fun setProducts(products : List<Product>) {
        this.mProducts = products
    }

    override fun getItemCount(): Int {
        if(mProducts != null)
            return mProducts!!.size
        return 0
    }

    override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
        if(mProducts != null) {
            val current = mProducts!!.get(position)
            holder.setText(current.code)
        } else {
            holder.setText(context.resources.getString(R.string.lbl_no_list_created))
        }
    }

    fun getProductAtPosition(position: Int) : Product {
        return mProducts!!.get(position)
    }

ProductViewHolder:

private var productItemView : TextView = itemView.findViewById(R.id.productItemRecyclerView)

    fun setText(current: String) {
        productItemView.text = current
    }

知道为什么在 products_in_productlist_table 表中创建新行时,LiveData 没有更新吗?

【问题讨论】:

  • 你能分享你的 ProductAdapter 吗?
  • @Ferran 当然!已添加到说明中
  • @Stavro 比我快 notifyDataSetChanged() 不见了。

标签: android android-room android-livedata


【解决方案1】:

在 AdapterClass 的方法中添加 notifyDataSetChange()

fun setProducts(products : List<Product>) {
        this.mProducts = products
        notifyDataSetChange()
    }

【讨论】:

  • 非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-30
  • 1970-01-01
  • 2018-02-10
  • 2020-08-16
  • 1970-01-01
相关资源
最近更新 更多