0

私はRxJava2、KotlinとRoomを使用しています。ここでRecyclerのチェックボックスをオンにすると、アイテムが真にチェックされます。immedietalyはfalseにチェックされます

は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 
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アイテムの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 subscribeメソッドでは、チェックボックスを更新した後、取り出した更新項目が正しくチェックされていますが( "isCompleted")、アダプタの設定が間違っています。私のonBindViewHolderメソッドでは、チェックされるように設定された項目は常にfalseであるため、アダプタのリスト項目が正しく更新されていないようです。

正常に動作させるにはどうすればいいですか?

私はアプリを再起動した場合でも、チェックボックスがtrueに設定されていないUPDATE

、DBからしかしフェッチされたアイテムは、属性をtrueに設定された「完了する」を持っています。問題はアダプタに実際には、私はなぜ私は期待どおりの項目がないのか分かりません - 私はアダプティブにアイテムをフェッチしている私のサブスクライブメソッドでは、アダプタに正しくあります。

答えて

1

uはplsはこの機能をチェックすることができ

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() 
       }) 

あなたは、更新がデータベースに存在しているときには、このメソッドと呼ばれます、次のコードの意志を購読意味し、流動性のある買い物リストのために加入しています完了した値を偽にリセットしてください。

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

はい、ありがとうございます。私はそれを正しく設定するのを忘れました:ShoppingListElementItem(it.id、it.name、it.isCompleted、it.timestamp) – Konrad

+0

実際には、私は 'id'プロパティを削除しました、それはunnessecearyです。とにかく、もう一度ありがとう – Konrad

+0

恐ろしい。 @okset – lib4

0

私はあなたがチェックボックスをクリックすると、問題がコード

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

のこのブロックであると考え、isCheckedは真であると私は間違っていないよ場合は、listener.onClick(position,isChecked)RecyclerViewで同じ項目をクリックします。 ShoppingItemCheckboxListenerは何をしますか?この機能で

+0

こんにちは、質問を更新しました。私はRecyclerViewアイテムのチェックボックスがチェックされているので、ViewModelでアイテムを更新することができるように、このリスナーをホスティングアクティビティと通信できるようにしました – Konrad

関連する問題