选中为true时,Recycler View项目中的复选框立即被检查为false

问题描述 投票:0回答:2

我使用RxJava2,Kotlin和Room作为我的例子。

这是用于将我的项目填充到recyclerView的适配器:

class ShoppingListDetailsAdapter(val list: ArrayList<ShoppingListElementItem>, val context: Context, val listener: ShoppingItemCheckboxListener, val isArchived: Boolean) : RecyclerView.Adapter<ShoppingListDetailsAdapter.ViewHolder>() {

override fun getItemCount(): Int {
    return list.count()
}

override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
    val itemView = LayoutInflater.from(parent?.getContext())
            .inflate(R.layout.item_shopping_list_element, parent, false)
    return ViewHolder(itemView)
}

override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
    val item = list.get(position)
    holder?.name?.setText(item.name)
    if(item.isCompleted){
        holder?.isCompleted?.isChecked = true
    }


    if(isArchived)
    holder?.isCompleted?.isEnabled = false
    else{
        holder?.isCompleted?.isEnabled = true
    }

    holder?.isCompleted?.setOnCheckedChangeListener{
        buttonView, isChecked ->
        item.isCompleted = isChecked
        listener.onClick(position, isChecked)
    }


}


inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    var name: TextView
    var isCompleted: CheckBox
    private var viewClickListener: ShoppingItemCheckboxListener? = null


    init {
        name = view.findViewById(R.id.itemName)
        isCompleted = view.findViewById(R.id.checkbox)
    }


}

fun removeItem(position: Int) {
    list.removeAt(position)
    // notify the item removed by position
    // to perform recycler view delete animations
    // NOTE: don't call notifyDataSetChanged()
    notifyItemRemoved(position)
}

fun restoreItem(item: ShoppingListElementItem, position: Int) {
    list.add(position, item)
    // notify item added by position
    notifyItemInserted(position)
   }
}

这是我的ViewModel:

class ShoppingListViewModel(private val dataSource: ShoppingListDao) : ViewModel() {

fun createShoppingList(listName: String){
    val arrayList = ArrayList<ShoppingListItem>()
    val shoppingList = ShoppingList(name = listName, isArchived = false, items = arrayList, timestamp = Date())
    dataSource.insertShoppingList(shoppingList)
}

fun createShoppingListItem(itemName: String, shoppingListId: Int){
    dataSource.getShoppingList(shoppingListId)
            .firstElement()
            .subscribe {
                shoppingList: ShoppingList ->
                val items = shoppingList.items
                 items.add(ShoppingListItem(itemName, false, Date()))

                dataSource.updateShoppingList(shoppingList = shoppingList)
            }
}

fun getShoppingLists(): Flowable<List<ShoppingList>> {
    return dataSource.getActiveShoppingLists()
            .map {
                t -> t.sortedByDescending { it.timestamp }
            }
}

fun getArchivedLists(): Flowable<List<ShoppingList>> {
    return dataSource.getArchivedShoppingLists()
            .map {
                t -> t.sortedByDescending { it.timestamp }
            }

}

fun getShoppingList(id: Int): Flowable<ShoppingList> {
    return dataSource.getShoppingList(id)
}

fun archiveItem(deletedShoppingListItem: com.app.shoppinglistapp.ui.ShoppingListDTO) {

   dataSource.archiveShoppingList(deletedShoppingListItem.id)
}

fun reArchiveItem(deletedShoppingListItem: com.app.shoppinglistapp.ui.ShoppingListDTO){

    dataSource.reArchiveShoppingList(deletedShoppingListItem.id)
}

fun removeShoppingListItem(deletedItem: ShoppingListElementItem, shoppingListId: Int) {
    dataSource.getShoppingList(shoppingListId)
            .firstElement()
            .subscribe {
                shoppingList: ShoppingList ->
                val items: ArrayList<ShoppingListItem> = shoppingList.items

                val filter = items.filter {
                    it.timestamp != deletedItem.timestamp
                }

                dataSource.updateShoppingList(shoppingList = ShoppingList(id = shoppingList.id,
                        name = shoppingList.name,
                        isArchived = shoppingList.isArchived,
                        timestamp = shoppingList.timestamp,
                        items = filter as ArrayList<ShoppingListItem>
                        ))
            }
}

fun restoreShoppingListItem(deletedItem: ShoppingListElementItem, shoppingListId: Int) {
    dataSource.getShoppingList(shoppingListId)
            .firstElement()
            .subscribe {
                shoppingList: ShoppingList ->
                val items = shoppingList.items
                items.add(ShoppingListItem(deletedItem.name, deletedItem.isCompleted, deletedItem.timestamp))
                dataSource.updateShoppingList(shoppingList = ShoppingList(id = shoppingList.id,
                        name = shoppingList.name,
                        isArchived = shoppingList.isArchived,
                        timestamp = shoppingList.timestamp,
                        items = items
                ))
            }
}

fun updateShoppingList(shoppingList: ArrayList<ShoppingListElementItem>, shoppingListId: Int) {
    dataSource.getShoppingList(shoppingListId)
            .firstElement()
            .subscribe {
                t: ShoppingList ->

                val dbShoppingList = ArrayList<ShoppingListItem>()
                shoppingList.forEach {
                    it -> dbShoppingList.add(ShoppingListItem(it.name, it.isCompleted, it.timestamp))
                }

                dataSource.updateShoppingList(shoppingList = ShoppingList(id = t.id,
                        name = t.name,
                        isArchived = t.isArchived,
                        timestamp = t.timestamp,
                        items = dbShoppingList
                ))
            }
}
}

这是我的Dao界面:

@Dao
interface ShoppingListDao {
@Query("SELECT * FROM shopping_list where id = :id limit 1")
fun getShoppingList(id: Int): Flowable<ShoppingList>

@Query("SELECT * FROM shopping_list where not is_archived")
fun getActiveShoppingLists(): Flowable<List<ShoppingList>>

@Query("SELECT * FROM shopping_list where is_archived")
fun getArchivedShoppingLists(): Flowable<List<ShoppingList>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertShoppingList(shoppingList: ShoppingList)

@Update
fun updateShoppingList(shoppingList: ShoppingList)

@Query("UPDATE shopping_list SET is_archived = 1 where id = :id")
fun archiveShoppingList(id: Int)

@Query("UPDATE shopping_list SET  is_archived = 0 where id = :id")
fun reArchiveShoppingList(id: Int)
}

这是活动:

class ShoppingListDetailsActivity : AppCompatActivity(), RecyclerItemTouchHelper.RecyclerItemTouchHelperListener, ShoppingItemCheckboxListener {

private lateinit var viewModelFactory: ViewModelFactory
private lateinit var viewModel: ShoppingListViewModel
private var intExtra: Int? = null
private var isArchived: Boolean? = null
private val disposable = CompositeDisposable()
private var shoppingList = ArrayList<ShoppingListElementItem>()
private var mAdapter: ShoppingListDetailsAdapter? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main2)
    setSupportActionBar(toolbar)

    supportActionBar!!.setDisplayHomeAsUpEnabled(true)

    intExtra = getIntent().getIntExtra("id", 0)
    isArchived = getIntent().getBooleanExtra("isArchived", false)

    viewModelFactory = Injection.provideViewModelFactory(this)
    viewModel = ViewModelProviders.of(this, viewModelFactory).get(ShoppingListViewModel::class.java)

 //        mAdapter = ShoppingListDetailsAdapter(shoppingList, this, this, isArchived!!)

    val mLayoutManager = LinearLayoutManager(applicationContext)
    recyclerView.setLayoutManager(mLayoutManager)
    recyclerView.setItemAnimator(DefaultItemAnimator())
    recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
 //        recyclerView.setAdapter(mAdapter)

    if (isArchived as Boolean) {
        fab.visibility = View.GONE
    }
    else{
        fab.setOnClickListener { view ->
            val alertDialogAndroid = getShoppingListDialog()
            alertDialogAndroid?.show()
        }
    }

    val itemTouchHelperCallback1 = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
        override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
            return true
        }

        override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
            // Row is swiped from recycler view
            // remove it from adapter
            if (viewHolder is ShoppingListDetailsAdapter.ViewHolder) {
                // get the removed item name to display it in snack bar
                val name = shoppingList[viewHolder.adapterPosition].name

                // backup of removed item for undo purpose
                val deletedItem = shoppingList[viewHolder.adapterPosition]
                val deletedIndex = viewHolder.adapterPosition

                // remove the item from recycler view
                mAdapter?.removeItem(viewHolder.adapterPosition)
                viewModel.removeShoppingListItem(deletedItem, intExtra!!)


                // showing snack bar with Undo option
                val snackbar = Snackbar
                        .make(coordinatorLayout, name + " is deleted!", Snackbar.LENGTH_LONG)
                snackbar.setAction("UNDO", View.OnClickListener {
                    // undo is selected, restore the deleted item
                    mAdapter?.restoreItem(deletedItem, deletedIndex)
                    viewModel.restoreShoppingListItem(deletedItem, intExtra!!)
                })
                snackbar.setActionTextColor(Color.YELLOW)
                snackbar.show()
            }
            Log.v("Test", "test")
        }

        override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
        }
    }

    if (!isArchived!!)
        ItemTouchHelper(itemTouchHelperCallback1).attachToRecyclerView(recyclerView)
}

fun getShoppingListDialog(): AlertDialog? {
    val layoutInflaterAndroid = LayoutInflater.from(this)
    val mView = layoutInflaterAndroid.inflate(R.layout.dialog_input_name, null)
    val alertDialogBuilderUserInput = AlertDialog.Builder(this)
    alertDialogBuilderUserInput.setView(mView)

    val userInputDialogEditText = mView.findViewById(R.id.userInputDialog) as EditText
    alertDialogBuilderUserInput
            .setCancelable(false)
            .setPositiveButton("Send", DialogInterface.OnClickListener { dialogBox, id ->
                viewModel.createShoppingListItem(userInputDialogEditText.text.toString(), intExtra!!)
            })

            .setNegativeButton("Cancel",
                    DialogInterface.OnClickListener { dialogBox, id -> dialogBox.cancel() })

    return alertDialogBuilderUserInput.create()
}

override fun onSupportNavigateUp(): Boolean {
    onBackPressed()
    return true
}

override fun onStart() {
    super.onStart()
    if (intExtra != null)
        viewModel.getShoppingList(intExtra!!)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ t ->
                    shoppingList.clear()
                    t.items.forEach {
                        val item = ShoppingListElementItem(0, it.name, false, it.timestamp)
                        shoppingList.add(item)

                    }
                    shoppingList.size
                    mAdapter = ShoppingListDetailsAdapter(shoppingList, this, this, isArchived!!)
                    recyclerView.setAdapter(mAdapter)
//                        mAdapter?.notifyDataSetChanged()
                })
}

override fun onStop() {
    super.onStop()

    // clear all the subscription
    disposable.clear()
}

override fun onClick(position: Int, isChecked: Boolean) {
    shoppingList.get(position).isCompleted = isChecked
    viewModel.updateShoppingList(shoppingList, intExtra!!)
    Toast.makeText(applicationContext, "isChecked: ${isChecked}", Toast.LENGTH_SHORT).show()
}

override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int, position: Int) {
}

}

当我试图检查我的RecyclerView项目中的复选框时,立即检查为false。

这是模型实体:

@Entity(tableName = "shopping_list")
data class ShoppingList(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    val id: Int = 0,
    @ColumnInfo(name = "name")
    val name: String,
    @ColumnInfo(name = "is_archived")
    val isArchived: Boolean,
    @ColumnInfo(name = "timestamp")
    val timestamp: Date,
    @ColumnInfo(name = "items")
    val items: ArrayList<ShoppingListItem>
)

data class ShoppingListItem(
    val name: String,
    val isCompleted: Boolean,
    val timestamp: Date
)

购物清单项目的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:orientation="horizontal"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<CheckBox
    android:id="@+id/checkbox"
    android:layout_weight="1"
    android:layout_width="0dp"
    android:layout_height="match_parent" />

<TextView
    android:id="@+id/itemName"
    android:layout_gravity="start"
    tools:text="GOWNO"
    android:layout_weight="1"
    android:textAlignment="textStart"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</LinearLayout>

和ShoppingListElementItem类:

data class ShoppingListElementItem(
    var id: Int,
    var name: String,
    var isCompleted: Boolean,
    val timestamp: Date
)

听众:

interface ShoppingItemCheckboxListener {

fun onClick(position: Int, isChecked: Boolean)
}

当我试图检查我的RecyclerView项目中的复选框时,它立即被检查回错。在更新复选框后的我的Acitivty订阅方法中,从db获取的更新项目被正确设置为选中(“isCompleted”),但我想我的适配器设置有问题。在我的onBindViewHolder方法中,设置为选中的项始终为false,因此我猜它没有正确更新适配器列表项。

如何让它正常工作?

UPDATE

即使我重新启动应用程序,复选框也不会设置为true,但是从db获取的项目将属性“isCompleted”设置为true。问题是在适配器真的,我不知道为什么它没有我期望的项目 - 在我的订阅方法在Activity中,我正在获取要填充到他们正确的适配器的项目。

android android-recyclerview kotlin android-adapter rx-java2
2个回答
1
投票

你可以检查这个功能吗?

override fun onStart() {
    super.onStart()
    if (intExtra != null)
        viewModel.getShoppingList(intExtra!!)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ t ->
                    shoppingList.clear()
                    t.items.forEach {
                        val item = ShoppingListElementItem(0, it.name, false, it.timestamp)
                        shoppingList.add(item)

                    }
                    shoppingList.size
                    mAdapter = ShoppingListDetailsAdapter(shoppingList, this, this, isArchived!!)
                    recyclerView.setAdapter(mAdapter)
//                        mAdapter?.notifyDataSetChanged()
                })

在这个函数中,您订阅了可流动的购物清单,这意味着只要数据库中有更新,这个订阅方法就会被调用,下面的代码会将完成的值重置为false

ShoppingListElementItem(0, it.name, false, it.timestamp)

0
投票

我认为问题在于这段代码

 holder?.isCompleted?.setOnCheckedChangeListener{
    buttonView, isChecked ->
    item.isCompleted = isChecked
    listener.onClick(position, isChecked)
}

当您单击复选框时,isChecked为true,如果我没有记错,listener.onClick(position,isChecked)会点击RecyclerView中的相同项目。 ShoppingItemCheckboxListener做什么?

© www.soinside.com 2019 - 2024. All rights reserved.