滑动刷新后删除项目不更新 RecyclerView

Remove Item Not Updating RecyclerView After Swipe Refresh

我在 RecyclerView 中实现了滑动删除项目以及拉动刷新项目。删除按预期工作,直到我执行拉动刷新。拉动刷新后,当我执行删除时,回收站视图似乎没有响应 notifyItemRemoved.

我也试过 notifyDataSetChanged 结果相同。

正在检索和更新数据:

private fun callForEarthquakeData() {
    swipe_refresh.isRefreshing = true
    earthquakeApiEndpoint.getEarthquakes()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeBy(::errorOnGetEarthquakes, ::successOnGetEarthquakes)
}

在成功调用数据后设置RecyclerView

private fun successOnGetEarthquakes(it: EarthquakeFeed) {
    swipe_refresh.isRefreshing = false
    rvEarthQuakes.layoutManager = LinearLayoutManager(this)
    adapter = AdapterEarthquake(this, it.features.toMutableList())
    rvEarthQuakes.adapter = adapter
    val dragDirs = ItemTouchHelper.UP or ItemTouchHelper.DOWN
    val recyclerItemTouchHelper = RecyclerItemTouchHelper(dragDirs, adapter)
    val itemTouchHelper = ItemTouchHelper(recyclerItemTouchHelper)
    itemTouchHelper.attachToRecyclerView(rvEarthQuakes)
}

滑动刷新布局以检索数据的侦听器:

swipe_refresh.setOnRefreshListener { callForEarthquakeData() }

完整适配器代码:

class AdapterEarthquake(private val context: Context, private val items: MutableList<Feature>)
    : RecyclerView.Adapter<RecyclerView.ViewHolder>(), ItemTouchHelperAdapter {

    private val sdf = SimpleDateFormat(context.getString(R.string.earthquake_date_format), Locale.US)

    override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
        Collections.swap(items, fromPosition, toPosition)
        notifyItemMoved(fromPosition, toPosition)
        return true
    }

    override fun onItemDismiss(position: Int) {
        items.removeAt(position)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
            ViewHolder(LayoutInflater.from(parent.context)
                    .inflate(R.layout.quake_list_item, parent, false))

    override fun getItemCount(): Int = items.size

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val viewHolder = holder as ViewHolder
        val item = items[position]
        val formattedLocalDateTime = sdf.format(item.properties.time)
        val formattedCoordinates = item.geometry.coordinates.let { "[${it[0]}, ${it[1]}, ${it[2]}]" }
        viewHolder.title.text = item.properties.title
        viewHolder.date.text = formattedLocalDateTime
        viewHolder.coordinates.text = formattedCoordinates

        when {
            item.properties.magnitude >= 7 -> viewHolder.itemView.setBackgroundColor(Color.RED)
            item.properties.magnitude >= 5 -> viewHolder.itemView.setBackgroundColor(ContextCompat.getColor(context, R.color.lightRed))
            else -> viewHolder.itemView.setBackgroundColor(Color.WHITE)
        }
    }

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        init {
            view.setOnClickListener {
                context.startActivity(Intent(
                        Intent.ACTION_VIEW, Uri.parse(items[adapterPosition].properties.detailsUrl)))
            }
        }

        val title = view.quake_title!!
        val coordinates = view.quake_coordinates!!
        val date = view.quake_date!!
    }
}

我希望 RecyclerView 在调用 notifyDataSetChanged() 后用删除的项目进行更新(就像在刷卡数据刷新之前所做的那样),但结果如下。

我认为问题出在您再次拉动并刷新 RecyclerView 时设置新项目的位置。在 successOnGetEarthquakes 方法中,每次从服务器获取数据时都会初始化一个新的适配器。

您可以只更改传递给适配器的列表并在您的适配器上调用 notifyDataSetChanged()。我只是在 Java 中提出了一些伪代码。希望对您有所帮助!

private fun successOnGetEarthquakes(it: EarthquakeFeed) {
    swipe_refresh.isRefreshing = false
    rvEarthQuakes.layoutManager = LinearLayoutManager(this)

    // Just feed the list, do not create a new adapter
    if(adapter != null) {
        adapter = AdapterEarthquake(this, it.features.toMutableList())
        rvEarthQuakes.adapter = adapter
    }
    else adapter.setItemsList(it.features.toMutableList())

    // Call the notifyDataSetChanged here
    adapter.notifyDataSetChanged()

    val dragDirs = ItemTouchHelper.UP or ItemTouchHelper.DOWN
    val recyclerItemTouchHelper = RecyclerItemTouchHelper(dragDirs, adapter)
    val itemTouchHelper = ItemTouchHelper(recyclerItemTouchHelper)
    itemTouchHelper.attachToRecyclerView(rvEarthQuakes)
}

因此在您的适配器中创建一个新函数,它只更改 items 列表。我希望你明白了。