尝试交换项目时,ItemTouchHelper抛出IndexOutOfBoundException

时间:2019-04-24 17:14:30

标签: kotlin

我有一个RecyclerView,它添加了应该拖放的项目,但是,当添加项目时,我尝试将其交换,并抛出IndexOutOfBoundException

RecyclerView观察到一个ViewModel,当添加了某些块时,该ViewModel会刷新信息,我已经使用LiveData来实现它。

当列表中有一定数量的项目时,我的解决方案效果很好,当我尝试向RecyclerView中添加某些内容时,就会出现问题。

我已经用包含以下内容的类扩展了ItemTouchHelper.SimpleCallBack RecyclerView的适配器,但是当添加项目时,大小却不会改变(我尝试过手动设置,但无法使用)。

我试图通过调用来分离TouchHelper

touchHelper?.attachToRecyclerView(null)

,然后使用新的回调将其重新附加,但也无法正常工作。

这就是活动


class CreateWorkflowActivity: AppCompatActivity(), View.OnClickListener {

    var touchHelper:ItemTouchHelper?= null
    private lateinit var callback:ItemMoveCallback
    private lateinit var rec_view: RecyclerView
    companion object {
        private lateinit var viewModel : WorkflowViewModel
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_create_workflow)
        val factory= InjectorUtils.provideWorkflowViewModelFactory("")
        viewModel = ViewModelProviders.of(this,factory).get(WorkflowViewModel::class.java)
        rec_view= findViewById(R.id.recyclerView_addedBlocksOnCreation)
        rec_view.layoutManager= LinearLayoutManager(this)
        val observer = Observer<ArrayList<String>>{
            val adapter = BlockViewAdapter(it!!, this@CreateWorkflowActivity)
            callback= ItemMoveCallback(adapter,this@CreateWorkflowActivity,ItemTouchHelper.UP.or(ItemTouchHelper.DOWN),0)
            touchHelper= ItemTouchHelper(callback)
            touchHelper?.attachToRecyclerView(rec_view)
            runOnUiThread{
                rec_view.adapter= adapter
            }
        }
        viewModel.getLiveBlockNames().observe(this,observer)


    }

//this gets called when the user has decided the parameters for the block
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if(requestCode == 1) {
            if(resultCode==Activity.RESULT_OK) {

               //all block additions

                }

            }

        }

    }

}


这扩展了ItemTouchHelper.SimpleCallBack


class ItemMoveCallback(adapter: BlockViewAdapter, context: Context, dragDirs: Int, swipeDirs: Int) : ItemTouchHelper.SimpleCallback(dragDirs, swipeDirs)
{
    var mAdapter = adapter


    override fun onSwiped(p0: RecyclerView.ViewHolder, p1: Int) {
        return
    }

    override fun onMove(p0: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        mAdapter.swapItems(viewHolder.adapterPosition, target.adapterPosition)
        return true
    }
    fun setAdapter(adapter: BlockViewAdapter){
        mAdapter=adapter
    }

}

这是适配器(我已经省略了BlockViewHolder,因为它很标准)

class BlockViewAdapter(val dataset: ArrayList<String>,val context: Context): RecyclerView.Adapter<BlockViewHolder>(){

    @SuppressLint("ClickableViewAccessibility")
    override fun onBindViewHolder(holder: BlockViewHolder, position: Int) {
        holder.tView?.text = dataset[position]

        }


    override fun getItemCount(): Int {
        return dataset.size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlockViewHolder {

        return BlockViewHolder(
            LayoutInflater.from(context).inflate(
                R.layout.block_item,
                parent,
                false
            )
        )

    }

    fun swapItems(fromPosition: Int, toPosition: Int) {

        if (fromPosition < toPosition) {
            for (i in fromPosition..toPosition - 1) {
                dataset.set(i, dataset.set(i+1, dataset.get(i)))
            }
        } else {
            for (i in fromPosition..toPosition + 1) {
                dataset.set(i, dataset.set(i-1, dataset.get(i)))
            }
        }

        notifyItemMoved(fromPosition, toPosition)
    }


}

1 个答案:

答案 0 :(得分:0)

@Ludovico Brocca您正在遇到IndexOutOfBoundException,因为在向适配器添加新项后没有调用notifyDataSetChanged()

因此,仅使用上下文初始化适配器,然后将各项作为设置器。 以下示例可供参考:

class BlockViewAdapter(val context: Context) : RecyclerView.Adapter<BlockViewHolder>() {

    var dataset: List<String> = emptyList()
      set(value) {
        // might have to do this on main thread
        field = value
        notifyDataSetChanged()
      }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlockViewHolder {
      TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun onBindViewHolder(holder: BlockViewHolder, position: Int) {
      TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun getItemCount(): Int {
      TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

  }