我目前拥有一个功能全面的可扩展RecyclerView
(具有两个不同的视图:一个用于标题,另一个用于每个标题的内容)。标题下的每张卡的内容都是通过API调用检索到我的后端的。
今天,我设法实现了滑动以刷新功能,但是问题是当我执行刷新时,所有组都崩溃了。从UI / UX角度来看,这不是很吸引人,并为用户增加了额外的步骤。因此,我正在寻找一种执行刷卡刷新而不使组崩溃的方法(即卡的内容已更新,但卡与调用刷新时的位置相同)。我已经看过使用here和here的答案中详细介绍的onSaveInstanceState
和onRestoreInstanceState
,但无济于事。
我的适配器代码如下:
class BusStopsServicesArrivalRVAdapter :
RecyclerView.Adapter<RecyclerView.ViewHolder>(), BusStopNoSectionHeaderViewHolder.HeaderViewHolderCallback {
private val SERVICE_TYPE = 1
private val STOP_TYPE = 2
private var busStopServiceList: ArrayList<BusStopService>? = null
private var busStopList: ArrayList<String>? = null
private var busArrivalViewTypes: SparseArray<BusArrivalViewType>? = null
private var headerExpandTracker: SparseIntArray? = null
lateinit var context: Context
var nineOneCount = 0
var threeOneCount = 0
var threeNineCount = 0
var fiveNineCount = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view: View
when (viewType) {
SERVICE_TYPE -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.card_bus_stop_service, parent, false)
return BusStopServiceHolder(view)
}
STOP_TYPE -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.card_bus_stop_section, parent, false)
return BusStopNoSectionHeaderViewHolder(view, this)
}
else -> {
view = LayoutInflater.from(parent.context)
.inflate(R.layout.card_bus_stop_service, parent, false)
return BusStopServiceHolder(view)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val itemViewType = getItemViewType(position)
val viewType = busArrivalViewTypes!!.get(position)
if (itemViewType == SERVICE_TYPE) {
bindBusStopServiceViewHolder(holder, viewType)
} else {
bindHeaderViewHolder(holder, position, viewType)
}
}
private fun bindHeaderViewHolder(holder: RecyclerView.ViewHolder, position: Int, busArrivalViewType: BusArrivalViewType) {
val dataIndex = busArrivalViewType.dataIndex
val headerViewHolder = holder as BusStopNoSectionHeaderViewHolder
when(busStopList!![dataIndex]) {
"D" -> {
headerViewHolder.busStopNoTextView.text =
context.resources.getString(R.string.bus_stop_services_description_D)
}
"C" -> {
headerViewHolder.busStopNoTextView.text =
context.resources.getString(R.string.bus_stop_services_description_C)
}
"B" -> {
headerViewHolder.busStopNoTextView.text =
context.resources.getString(R.string.bus_stop_services_description_B)
}
"A" -> {
headerViewHolder.busStopNoTextView.text =
context.resources.getString(R.string.bus_stop_services_description_A)
}
}
// headerViewHolder.busStopNoTextView.text = busStopList!![dataIndex]
if (isExpanded(position)) {
headerViewHolder.busStopNoTextView
.setCompoundDrawablesWithIntrinsicBounds(null, null, headerViewHolder.arrowUp, null)
} else {
headerViewHolder.busStopNoTextView
.setCompoundDrawablesWithIntrinsicBounds(null, null, headerViewHolder.arrowDown, null)
}
}
private fun bindBusStopServiceViewHolder(holder: RecyclerView.ViewHolder, busArrivalViewType: BusArrivalViewType) {
val dataIndex = busArrivalViewType.dataIndex
(holder as BusStopServiceHolder).bindData(busStopServiceList!![dataIndex], context)
}
override fun getItemCount(): Int {
var count = 0
if (busStopList != null && busStopServiceList != null) {
busArrivalViewTypes!!.clear()
var collapsedCount = 0
for (i in busStopList!!.indices) {
busArrivalViewTypes!!.put(count, BusArrivalViewType(i, STOP_TYPE))
count += 1
val userType = busStopList!![i]
val childCount = getChildCount(userType)
if (headerExpandTracker!!.get(i) != 0) {
// Expanded State
for (j in 0 until childCount) {
busArrivalViewTypes!!.put(count, BusArrivalViewType(count - (i + 1) + collapsedCount, SERVICE_TYPE))
count += 1
}
} else {
// Collapsed
collapsedCount += childCount
}
}
}
return count
}
override fun getItemViewType(position: Int): Int {
return if (busArrivalViewTypes!!.get(position).type === STOP_TYPE) {
STOP_TYPE
} else {
SERVICE_TYPE
}
}
private fun getChildCount(type: String): Int {
when (type) {
"D" -> return nineOneCount
"C" -> return threeOneCount
"B" -> return threeNineCount
"A" -> return fiveNineCount
else -> return 0
}
}
fun setUserListAndType(busStopServiceList: ArrayList<BusStopService>?, busStopNoList: ArrayList<String>?, c: Context) {
if (busStopServiceList != null && busStopNoList != null) {
this.busStopServiceList = busStopServiceList
this.busStopList = busStopNoList
this.context = c
busArrivalViewTypes = SparseArray<BusArrivalViewType>(busStopServiceList.size + busStopNoList.size)
headerExpandTracker = SparseIntArray(busStopNoList.size)
notifyDataSetChanged()
for (i in busStopServiceList.indices) {
when(busStopServiceList[i].busStopCode) {
"D" -> {
nineOneCount += 1
}
"C" -> {
threeOneCount += 1
}
"B" -> {
threeNineCount += 1
}
"A" -> {
fiveNineCount += 1
}
}
}
}
}
override fun onHeaderClick(position: Int) {
val viewType = busArrivalViewTypes!!.get(position)
val dataIndex = viewType.dataIndex
val userType = busStopList!![dataIndex]
val childCount = getChildCount(userType)
if (headerExpandTracker!!.get(dataIndex) == 0) {
headerExpandTracker!!.put(dataIndex, 1)
notifyItemRangeInserted(position + 1, childCount)
} else {
headerExpandTracker!!.put(dataIndex, 0)
notifyItemRangeRemoved(position + 1, childCount)
}
}
override fun isExpanded(position: Int): Boolean {
val dataIndex = busArrivalViewTypes!!.get(position).dataIndex
return headerExpandTracker!!.get(dataIndex) == 1
}
}