예를 들어 RxJava2, Kotlin 및 Room을 사용하고 있습니다. 여기 Recycler의 체크 박스 항목을 선택하면 항목이 거짓으로 표시됩니다.
가 recyclerView 내 항목을 채우기위한 어댑터입니다 : 여기@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 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
))
}
}
}
내 다오 인터페이스입니다 : 여기
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)
}
}
나의 뷰 모델입니다 활동 :
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 항목에서 checbox를 확인하려고 할 때 immedietaly가 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 항목의 확인란을 선택하려고하면 immedietaly가 false로 다시 검사됩니다. 내 Acitivty 구독 방법에서 체크 상자를 업데이트 한 후 db에서 가져온 업데이트 된 항목이 올바르게 ("isCompleted") 확인되도록 설정되었지만 어댑터 설정에 문제가있는 것 같습니다. 내 onBindViewHolder 메서드에서 확인하도록 설정된 항목은 항상 false이므로 어댑터 목록 항목이 제대로 업데이트되지 않았을 것입니다.
제대로 작동시키는 방법은 무엇입니까? 내가 응용 프로그램을 다시 시작할 때
UPDATE
조차, 체크 박스는 그러나 DB에서 가져온 항목이 true로 설정 "대한 IsCompleted"는 속성이 true로 설정되어 있지 않습니다. 문제는 어댑터에 실제로, 나는 그것이 내가 예상대로 항목이 없다는 것을 알지 못한다. - Activity에있는 구독 방법에서 어댑터에 채워지는 항목을 올바르게 가져오고있다.
예, 감사합니다. 나는 그것을 올바르게 설정하는 것을 잊어 버렸다 : ShoppingListElementItem (it.id, it.name, it.isCompleted, it.timestamp) – Konrad
사실, 나는 'id'속성을 제거했다. 어쨌든, 다시 감사합니다 – Konrad
굉장. @okset – lib4