如何使用实时数据从 RecyclerView 中删除项目?
How to delete item from RecyclerView with Live Data?
我在申请 Android 方面也是全新的(大概一周左右。)
我正在尝试根据数据库中的数据更改(使用 LiveData)使购物车片段 UI 实时更新,但我不知道如何使用该特定行中的按钮从购物车中删除一行.
我一直在谷歌搜索,但我真的被困住了,因为我不完全确定我在做什么。
这是我的购物车适配器的代码:
class CartAdapter(private var cartData: LiveData<List<Cart>>) : RecyclerView.Adapter<CartAdapter.ItemViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
//create a new view, which defines the UI of the list item
val view = LayoutInflater.from(parent.context).inflate(R.layout.cart_item,parent,false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.nameTV.text = cartData.value?.get(position)?.itemName
holder.priceTV.text = cartData.value?.get(position)?.itemPrice.toString()
holder.imagebtn.setOnClickListener {
deleteItem(position)
}
}
private fun deleteItem(position: Int)
{
notifyItemChanged(position)
cartData.observe(/**help here ;-;)*/)
}
override fun getItemCount(): Int {
return cartData.size
}
class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view){
var nameTV: TextView = view.findViewById(R.id.item_name_text_view)
var priceTV: TextView = view.findViewById(R.id.item_price_text_view)
var imagebtn: ImageButton = view.findViewById(R.id.clear_button)
}
}
这里是 CartFragment 的代码:
class CartFragment : Fragment() {
private val viewModel: ItemViewModel by activityViewModels {
ItemViewModelFactory(
(activity?.application as NiekBakehouseApplication).database.itemDao()
)
}
private var cartItems = viewModel.cartList
private var _binding: FragmentCartBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentCartBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter = CartAdapter(cartItems) //help here ;-;)
binding.recyclerView.layoutManager = LinearLayoutManager(this.context)
binding.recyclerView.adapter = adapter
viewModel.cartList.observe(viewLifecycleOwner,{binding.recyclerView.adapter?.notifyDataSetChanged()})
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
这是 DAO:
@Dao
interface ItemDao {
/**on conflict strat is used when there's a conflict when calling function
* this makes it ignores a new item if it's primary key already exists*/
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(item: Item)
@Update
suspend fun update(item: Item)
@Delete
suspend fun delete(item: Item)
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(cart: Cart)
@Update
suspend fun update(cart: Cart)
@Delete
fun delete(cart: Cart)
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(pesenan: Pesenan)
@Update
suspend fun update(pesenan: Pesenan)
@Delete
suspend fun delete(pesenan: Pesenan)
@Query("SELECT * FROM Item where iId = :id")
fun getItem(id: Long) : Flow<Item>
@Query("SELECT * FROM Pesenan where oId = :id")
fun getOrder(id: Long) : Flow<Pesenan>
@Query("SELECT * From Cart where iId = :id")
fun getCart(id: Long) : Flow<Cart>
@Query("SELECT * FROM Pesenan where oId = :id")
fun getOrder2(id: Long) : Pesenan
@Query("select itempesenancrossref.itemId as iId, itemName as itemName, itemPrice as itemPrice, quantity as itemQuantity from itempesenancrossref inner join item where item.iId = itempesenancrossref.itemId AND itempesenancrossref.orderId = :id") // need to get all items with the same in pesenan table via cross ref.
fun getItemsFromReference(id:Long):Flow<List<Item>>
@Query("select itempesenancrossref.itemId as iId, itemName as itemName, itemPrice as itemPrice, quantity as itemQuantity from itempesenancrossref inner join item where item.iId = itempesenancrossref.itemId AND itempesenancrossref.orderId = :id") // need to get all items with the same in pesenan table via cross ref.
fun getItemsFromReference2(id:Long):List<Item>
//get item by pesenan ID!
@Query("SELECT * FROM ItemPesenanCrossRef where orderId=:id")
fun getListItemId(id:Long): List<ItemPesenanCrossRef>
/**"SELECT * FROM plants WHERE id IN (SELECT DISTINCT(plant_id) FROM garden_plantings)*/
/**fun getPlantedGardens(): Flow<List<PlantAndGardenPlantings>>*/
@Transaction
@Query("SELECT * FROM Item where iId in (SELECT DISTINCT(itemId) FROM ItemPesenanCrossRef)")
fun getItemWithPesenans(): Flow<List<ItemsWithPesenan>>
@Transaction
@Query("SELECT * FROM Pesenan where oId = :id in (SELECT DISTINCT(orderId) FROM ItemPesenanCrossRef)")
fun getPesenanItems(id: Long): List<PesenanWithItems>
@Query("SELECT * FROM item")
fun getAllItems(): Flow<List<Item>>
@Query("SELECT * FROM pesenan")
fun getAllPesenan(): Flow<List<Pesenan>>
@Query("select * from cart")
fun getAllCartItem() : Flow<MutableList<Item>>
}
and this is ItemViewModel where the factory goes :
class ItemViewModel(private val itemDao: ItemDao) : ViewModel() {
val allItems: LiveData<List<Item>> = itemDao.getAllItems().asLiveData()
val allOrders: LiveData<List<Pesenan>> = itemDao.getAllPesenan().asLiveData()
val cartList: LiveData<MutableList<Item>> = itemDao.getAllCartItem().asLiveData()
/**
* Updates an existing Item in the database.
*/
fun updateItem(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
) {
val updatedItem = getUpdatedItemEntry(itemId, itemName, itemPrice, itemCount)
updateItem(updatedItem)
}
fun updateCart(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
) {
val updatedCart = getUpdatedCartEntry(itemId, itemName, itemPrice, itemCount)
updateCart(updatedCart)
}
/**
* Launching a new coroutine to update an item in a non-blocking way
*/
private fun updateItem(item: Item) {
viewModelScope.launch {
itemDao.update(item)
}
}
private fun updateCart(cart: Cart) {
viewModelScope.launch {
itemDao.update(cart)
}
}
/**
* Inserts the new Item into database.
*/
fun addNewItem(itemName: String, itemPrice: String, itemCount: Int) {
val newItem = getNewItemEntry(itemName, itemPrice, itemCount)
insertItem(newItem)
}
fun addToCart(itemId: Long, name: String, price: String, qty: Int)
{
val newCart = getNewCartEntry(itemId,name,price,qty)
insertCart(newCart)
}
/**
* Launching a new coroutine to insert an item in a non-blocking way
*/
private fun insertItem(item: Item) {
viewModelScope.launch {
itemDao.insert(item)
}
}
private fun insertCart(cart: Cart) {
viewModelScope.launch {
itemDao.insert(cart)
}
}
private fun insertPesenan(pesenan: Pesenan) {
viewModelScope.launch {
itemDao.insert(pesenan)
}
}
/**
* Launching a new coroutine to delete an item in a non-blocking way
*/
fun deleteItem(item: Item) {
viewModelScope.launch {
itemDao.delete(item)
}
}
fun deleteCart(cart: Cart) {
viewModelScope.launch {
itemDao.delete(cart)
}
}
fun deletePesenan(pesenan: Pesenan) {
viewModelScope.launch {
itemDao.delete(pesenan)
}
}
/**
* Retrieve an item from the repository.
*/
fun retrieveItem(id: Long): LiveData<Item> {
return itemDao.getItem(id).asLiveData()
}
fun retrievePesenan(id: Long): LiveData<Pesenan> {
return itemDao.getOrder(id).asLiveData()
}
fun retrieveCart(id: Long): LiveData<Cart>{
return itemDao.getCart(id).asLiveData()
}
//TODO: extract item list!
fun retrieveItemsFromOrder(orderIdTarget: Long): LiveData<List<Item>> {
return itemDao.getItemsFromReference(orderIdTarget).asLiveData()//look for the items associated in this particular order ID
/**get all items from crossref*/
}
fun retrieveItemsFromOrder2(orderIdTarget: Long): List<Item> {
return itemDao.getItemsFromReference2(orderIdTarget)//look for the items associated in this particular order ID
/**get all items from crossref*/
}
/**
* Returns true if the EditTexts are not empty
*/
fun isEntryValid(itemName: String, itemPrice: String): Boolean {
if (itemName.isBlank() || itemPrice.isBlank()) {
return false
}
return true
}
private fun getNewItemEntry(itemName: String, itemPrice: String, itemCount: Int): Item {
return Item(
iId = 0, //hopefully we can make this auto increment
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
private fun getNewCartEntry(itemId: Long, itemName: String, itemPrice: String, itemCount: Int): Cart {
return Cart(
iId = itemId, //hopefully we can make this NOT auto increment
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
/**
* Called to update an existing entry in the Inventory database.
* Returns an instance of the [Item] entity class with the item info updated by the user.
*/
private fun getUpdatedItemEntry(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
): Item {
return Item(
iId = itemId,
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
private fun getUpdatedCartEntry(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
): Cart {
return Cart(
iId = itemId,
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
}
class ItemViewModelFactory(private val itemDao: ItemDao) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass.isAssignableFrom(ItemViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return ItemViewModel(itemDao) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
这是购物车片段的 XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/item_name_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/item_name_header"
android:textSize="16sp"
android:gravity="center_horizontal"
android:padding="8dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="@id/arrival_time_header"
app:layout_constraintEnd_toStartOf="parent"/>
<TextView
android:id="@+id/arrival_time_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/item_price_header"
android:textSize="16sp"
android:gravity="center_horizontal"
android:padding="8dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/item_name_header"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:clipToPadding="false"
android:padding="16dp"
app:layout_constraintTop_toBottomOf="@id/arrival_time_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/constrabottom"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constrabottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ImageButton
android:id="@+id/decrease"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/ic_decrease"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/qty"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/qty"
android:layout_width="0dp"
android:layout_height="0dp"
android:textSize="12sp"
android:paddingStart="18dp"
android:paddingEnd="18dp"
app:layout_constraintStart_toEndOf="@id/decrease"
app:layout_constraintEnd_toStartOf="@id/increase"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageButton
android:id="@+id/increase"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_increase"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/qty"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/subtotal_enter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Subtotal"
style="@style/TextAppearance.MaterialComponents.Headline6"
app:layout_constraintStart_toStartOf="@id/subtotal_value"
app:layout_constraintBottom_toTopOf="@id/subtotal_value"
android:textSize="20sp"/>
<TextView
android:id="@+id/subtotal_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="50sp"
tools:text="8888" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
我刚刚完成了 developer.android.com 关于使用 Kotlin 构建应用程序的整个课程,但我不确定我正在做的事情的一半。
首先,不要在适配器中使用实时数据,删除实时数据,只需使用 private var cartData: 也可以在适配器中传递点击侦听器,然后在内部覆盖你的片段现在这是我的 Dao 删除方法
拿两个这样的列表
private var list: MutableList<DataTable>? = null
private var allListOfKeys: MutableList<DataTable>? = null
在你的观察者中像这样初始化列表
allListOfKeys = dataDao.getAllData().toMutableList()
allListOfKeys?.forEach {
list?.add(it)
}
allKeysAdapter.submitList(allListOfKeys)
然后在你的数据库中像这样删除它,这是我在 DAO 中的删除方法
@Query("DELETE from data_table WHERE id = :id")
suspend fun deleteCard(id: Int?)
这是我的删除点击监听器
override fun onDeleteClickListener(position: Int, item: DataTable) {
runOnUiThread {
MainScope().launch {
dataDao.deleteCard(item.id)
removeView(position, item)
}
}
}
private fun removeView(position: Int, item: DataTable) {
allListOfKeys?.remove(item)
binding.rvKeys.removeViewAt(position)
allKeysAdapter.notifyItemRemoved(position)
allKeysAdapter.notifyItemRangeChanged(position, allListOfKeys?.size!!)
allKeysAdapter.notifyDataSetChanged()
}
这是如何从该位置以及数据库中删除数据的示例
我在申请 Android 方面也是全新的(大概一周左右。) 我正在尝试根据数据库中的数据更改(使用 LiveData)使购物车片段 UI 实时更新,但我不知道如何使用该特定行中的按钮从购物车中删除一行.
我一直在谷歌搜索,但我真的被困住了,因为我不完全确定我在做什么。
这是我的购物车适配器的代码:
class CartAdapter(private var cartData: LiveData<List<Cart>>) : RecyclerView.Adapter<CartAdapter.ItemViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
//create a new view, which defines the UI of the list item
val view = LayoutInflater.from(parent.context).inflate(R.layout.cart_item,parent,false)
return ItemViewHolder(view)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.nameTV.text = cartData.value?.get(position)?.itemName
holder.priceTV.text = cartData.value?.get(position)?.itemPrice.toString()
holder.imagebtn.setOnClickListener {
deleteItem(position)
}
}
private fun deleteItem(position: Int)
{
notifyItemChanged(position)
cartData.observe(/**help here ;-;)*/)
}
override fun getItemCount(): Int {
return cartData.size
}
class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view){
var nameTV: TextView = view.findViewById(R.id.item_name_text_view)
var priceTV: TextView = view.findViewById(R.id.item_price_text_view)
var imagebtn: ImageButton = view.findViewById(R.id.clear_button)
}
}
这里是 CartFragment 的代码:
class CartFragment : Fragment() {
private val viewModel: ItemViewModel by activityViewModels {
ItemViewModelFactory(
(activity?.application as NiekBakehouseApplication).database.itemDao()
)
}
private var cartItems = viewModel.cartList
private var _binding: FragmentCartBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentCartBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val adapter = CartAdapter(cartItems) //help here ;-;)
binding.recyclerView.layoutManager = LinearLayoutManager(this.context)
binding.recyclerView.adapter = adapter
viewModel.cartList.observe(viewLifecycleOwner,{binding.recyclerView.adapter?.notifyDataSetChanged()})
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
这是 DAO:
@Dao
interface ItemDao {
/**on conflict strat is used when there's a conflict when calling function
* this makes it ignores a new item if it's primary key already exists*/
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(item: Item)
@Update
suspend fun update(item: Item)
@Delete
suspend fun delete(item: Item)
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(cart: Cart)
@Update
suspend fun update(cart: Cart)
@Delete
fun delete(cart: Cart)
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(pesenan: Pesenan)
@Update
suspend fun update(pesenan: Pesenan)
@Delete
suspend fun delete(pesenan: Pesenan)
@Query("SELECT * FROM Item where iId = :id")
fun getItem(id: Long) : Flow<Item>
@Query("SELECT * FROM Pesenan where oId = :id")
fun getOrder(id: Long) : Flow<Pesenan>
@Query("SELECT * From Cart where iId = :id")
fun getCart(id: Long) : Flow<Cart>
@Query("SELECT * FROM Pesenan where oId = :id")
fun getOrder2(id: Long) : Pesenan
@Query("select itempesenancrossref.itemId as iId, itemName as itemName, itemPrice as itemPrice, quantity as itemQuantity from itempesenancrossref inner join item where item.iId = itempesenancrossref.itemId AND itempesenancrossref.orderId = :id") // need to get all items with the same in pesenan table via cross ref.
fun getItemsFromReference(id:Long):Flow<List<Item>>
@Query("select itempesenancrossref.itemId as iId, itemName as itemName, itemPrice as itemPrice, quantity as itemQuantity from itempesenancrossref inner join item where item.iId = itempesenancrossref.itemId AND itempesenancrossref.orderId = :id") // need to get all items with the same in pesenan table via cross ref.
fun getItemsFromReference2(id:Long):List<Item>
//get item by pesenan ID!
@Query("SELECT * FROM ItemPesenanCrossRef where orderId=:id")
fun getListItemId(id:Long): List<ItemPesenanCrossRef>
/**"SELECT * FROM plants WHERE id IN (SELECT DISTINCT(plant_id) FROM garden_plantings)*/
/**fun getPlantedGardens(): Flow<List<PlantAndGardenPlantings>>*/
@Transaction
@Query("SELECT * FROM Item where iId in (SELECT DISTINCT(itemId) FROM ItemPesenanCrossRef)")
fun getItemWithPesenans(): Flow<List<ItemsWithPesenan>>
@Transaction
@Query("SELECT * FROM Pesenan where oId = :id in (SELECT DISTINCT(orderId) FROM ItemPesenanCrossRef)")
fun getPesenanItems(id: Long): List<PesenanWithItems>
@Query("SELECT * FROM item")
fun getAllItems(): Flow<List<Item>>
@Query("SELECT * FROM pesenan")
fun getAllPesenan(): Flow<List<Pesenan>>
@Query("select * from cart")
fun getAllCartItem() : Flow<MutableList<Item>>
}
and this is ItemViewModel where the factory goes :
class ItemViewModel(private val itemDao: ItemDao) : ViewModel() {
val allItems: LiveData<List<Item>> = itemDao.getAllItems().asLiveData()
val allOrders: LiveData<List<Pesenan>> = itemDao.getAllPesenan().asLiveData()
val cartList: LiveData<MutableList<Item>> = itemDao.getAllCartItem().asLiveData()
/**
* Updates an existing Item in the database.
*/
fun updateItem(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
) {
val updatedItem = getUpdatedItemEntry(itemId, itemName, itemPrice, itemCount)
updateItem(updatedItem)
}
fun updateCart(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
) {
val updatedCart = getUpdatedCartEntry(itemId, itemName, itemPrice, itemCount)
updateCart(updatedCart)
}
/**
* Launching a new coroutine to update an item in a non-blocking way
*/
private fun updateItem(item: Item) {
viewModelScope.launch {
itemDao.update(item)
}
}
private fun updateCart(cart: Cart) {
viewModelScope.launch {
itemDao.update(cart)
}
}
/**
* Inserts the new Item into database.
*/
fun addNewItem(itemName: String, itemPrice: String, itemCount: Int) {
val newItem = getNewItemEntry(itemName, itemPrice, itemCount)
insertItem(newItem)
}
fun addToCart(itemId: Long, name: String, price: String, qty: Int)
{
val newCart = getNewCartEntry(itemId,name,price,qty)
insertCart(newCart)
}
/**
* Launching a new coroutine to insert an item in a non-blocking way
*/
private fun insertItem(item: Item) {
viewModelScope.launch {
itemDao.insert(item)
}
}
private fun insertCart(cart: Cart) {
viewModelScope.launch {
itemDao.insert(cart)
}
}
private fun insertPesenan(pesenan: Pesenan) {
viewModelScope.launch {
itemDao.insert(pesenan)
}
}
/**
* Launching a new coroutine to delete an item in a non-blocking way
*/
fun deleteItem(item: Item) {
viewModelScope.launch {
itemDao.delete(item)
}
}
fun deleteCart(cart: Cart) {
viewModelScope.launch {
itemDao.delete(cart)
}
}
fun deletePesenan(pesenan: Pesenan) {
viewModelScope.launch {
itemDao.delete(pesenan)
}
}
/**
* Retrieve an item from the repository.
*/
fun retrieveItem(id: Long): LiveData<Item> {
return itemDao.getItem(id).asLiveData()
}
fun retrievePesenan(id: Long): LiveData<Pesenan> {
return itemDao.getOrder(id).asLiveData()
}
fun retrieveCart(id: Long): LiveData<Cart>{
return itemDao.getCart(id).asLiveData()
}
//TODO: extract item list!
fun retrieveItemsFromOrder(orderIdTarget: Long): LiveData<List<Item>> {
return itemDao.getItemsFromReference(orderIdTarget).asLiveData()//look for the items associated in this particular order ID
/**get all items from crossref*/
}
fun retrieveItemsFromOrder2(orderIdTarget: Long): List<Item> {
return itemDao.getItemsFromReference2(orderIdTarget)//look for the items associated in this particular order ID
/**get all items from crossref*/
}
/**
* Returns true if the EditTexts are not empty
*/
fun isEntryValid(itemName: String, itemPrice: String): Boolean {
if (itemName.isBlank() || itemPrice.isBlank()) {
return false
}
return true
}
private fun getNewItemEntry(itemName: String, itemPrice: String, itemCount: Int): Item {
return Item(
iId = 0, //hopefully we can make this auto increment
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
private fun getNewCartEntry(itemId: Long, itemName: String, itemPrice: String, itemCount: Int): Cart {
return Cart(
iId = itemId, //hopefully we can make this NOT auto increment
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
/**
* Called to update an existing entry in the Inventory database.
* Returns an instance of the [Item] entity class with the item info updated by the user.
*/
private fun getUpdatedItemEntry(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
): Item {
return Item(
iId = itemId,
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
private fun getUpdatedCartEntry(
itemId: Long,
itemName: String,
itemPrice: String,
itemCount: Int
): Cart {
return Cart(
iId = itemId,
itemName = itemName,
itemPrice = itemPrice.toDouble(),
itemQuantity = itemCount
)
}
}
class ItemViewModelFactory(private val itemDao: ItemDao) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass.isAssignableFrom(ItemViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return ItemViewModel(itemDao) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
这是购物车片段的 XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/item_name_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/item_name_header"
android:textSize="16sp"
android:gravity="center_horizontal"
android:padding="8dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="@id/arrival_time_header"
app:layout_constraintEnd_toStartOf="parent"/>
<TextView
android:id="@+id/arrival_time_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/item_price_header"
android:textSize="16sp"
android:gravity="center_horizontal"
android:padding="8dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/item_name_header"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:clipToPadding="false"
android:padding="16dp"
app:layout_constraintTop_toBottomOf="@id/arrival_time_header"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@id/constrabottom"
/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constrabottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<ImageButton
android:id="@+id/decrease"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/ic_decrease"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/qty"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/qty"
android:layout_width="0dp"
android:layout_height="0dp"
android:textSize="12sp"
android:paddingStart="18dp"
android:paddingEnd="18dp"
app:layout_constraintStart_toEndOf="@id/decrease"
app:layout_constraintEnd_toStartOf="@id/increase"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageButton
android:id="@+id/increase"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_increase"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/qty"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/subtotal_enter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Subtotal"
style="@style/TextAppearance.MaterialComponents.Headline6"
app:layout_constraintStart_toStartOf="@id/subtotal_value"
app:layout_constraintBottom_toTopOf="@id/subtotal_value"
android:textSize="20sp"/>
<TextView
android:id="@+id/subtotal_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="50sp"
tools:text="8888" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
我刚刚完成了 developer.android.com 关于使用 Kotlin 构建应用程序的整个课程,但我不确定我正在做的事情的一半。
首先,不要在适配器中使用实时数据,删除实时数据,只需使用 private var cartData: 也可以在适配器中传递点击侦听器,然后在内部覆盖你的片段现在这是我的 Dao 删除方法
拿两个这样的列表
private var list: MutableList<DataTable>? = null
private var allListOfKeys: MutableList<DataTable>? = null
在你的观察者中像这样初始化列表
allListOfKeys = dataDao.getAllData().toMutableList()
allListOfKeys?.forEach {
list?.add(it)
}
allKeysAdapter.submitList(allListOfKeys)
然后在你的数据库中像这样删除它,这是我在 DAO 中的删除方法
@Query("DELETE from data_table WHERE id = :id")
suspend fun deleteCard(id: Int?)
这是我的删除点击监听器
override fun onDeleteClickListener(position: Int, item: DataTable) {
runOnUiThread {
MainScope().launch {
dataDao.deleteCard(item.id)
removeView(position, item)
}
}
}
private fun removeView(position: Int, item: DataTable) {
allListOfKeys?.remove(item)
binding.rvKeys.removeViewAt(position)
allKeysAdapter.notifyItemRemoved(position)
allKeysAdapter.notifyItemRangeChanged(position, allListOfKeys?.size!!)
allKeysAdapter.notifyDataSetChanged()
}
这是如何从该位置以及数据库中删除数据的示例