【问题标题】:Remove Item Not Updating RecyclerView After Swipe Refresh滑动刷新后删除不更新 RecyclerView 的项目
【发布时间】:2019-05-15 07:43:39
【问题描述】:

我已经在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() 之后使用已删除的项目进行更新(就像在刷卡数据刷新之前一样),但结果如下。

【问题讨论】:

  • 我认为提供的代码没有任何问题。你能发布刷卡刷新代码吗?
  • @ReazMurshed 我已经从代码中包含了更完整的示例。如果还有什么可以帮助我知道的。
  • 我想这可能是模拟器的问题。上面的屏幕截图来自 Pixel 2 API 级别 28 模拟器。我现在将在我的三星 Galaxy S8 物理设备上试用并更新。
  • 确认同样的行为发生在我的三星 Galaxy S8 上,也运行 API 级别 28。
  • @ReazMurshed 我已在原始帖子中包含完整的适配器代码,谢谢。

标签: android kotlin android-recyclerview swiperefreshlayout


【解决方案1】:

我认为问题在于当您再次拉动并刷新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 列表。我希望你能明白。

【讨论】:

  • 很高兴知道这有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-22
  • 1970-01-01
相关资源
最近更新 更多