improved status list performance
This commit is contained in:
parent
e673a339c8
commit
d5fe843d8b
|
@ -372,7 +372,7 @@ class ParcelableActivitiesAdapter(
|
||||||
readInfoValueAction: (ActivityInfo) -> T,
|
readInfoValueAction: (ActivityInfo) -> T,
|
||||||
readStatusValueAction: (status: ParcelableActivity) -> T,
|
readStatusValueAction: (status: ParcelableActivity) -> T,
|
||||||
defValue: T, raw: Boolean = false): T {
|
defValue: T, raw: Boolean = false): T {
|
||||||
val data = data
|
val data = this.data
|
||||||
if (data is ObjectCursor) {
|
if (data is ObjectCursor) {
|
||||||
val dataPosition = position - activityStartIndex
|
val dataPosition = position - activityStartIndex
|
||||||
if (dataPosition < 0 || dataPosition >= getActivityCount(true)) {
|
if (dataPosition < 0 || dataPosition >= getActivityCount(true)) {
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.mariotaku.twidere.adapter
|
package org.mariotaku.twidere.adapter
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
|
||||||
import android.database.CursorIndexOutOfBoundsException
|
import android.database.CursorIndexOutOfBoundsException
|
||||||
import android.support.v4.widget.Space
|
import android.support.v4.widget.Space
|
||||||
import android.support.v7.widget.RecyclerView
|
import android.support.v7.widget.RecyclerView
|
||||||
|
@ -120,6 +119,7 @@ abstract class ParcelableStatusesAdapter(
|
||||||
private var displayDataCount: Int = 0
|
private var displayDataCount: Int = 0
|
||||||
private var showingActionCardId = RecyclerView.NO_ID
|
private var showingActionCardId = RecyclerView.NO_ID
|
||||||
private val reuseStatus = ParcelableStatus()
|
private val reuseStatus = ParcelableStatus()
|
||||||
|
private var infoCache: Array<StatusInfo?>? = null
|
||||||
|
|
||||||
override val itemCounts = ItemCounts(5)
|
override val itemCounts = ItemCounts(5)
|
||||||
|
|
||||||
|
@ -207,51 +207,48 @@ abstract class ParcelableStatusesAdapter(
|
||||||
|
|
||||||
override fun getItemId(position: Int): Long {
|
override fun getItemId(position: Int): Long {
|
||||||
val countIndex = getItemCountIndex(position)
|
val countIndex = getItemCountIndex(position)
|
||||||
when (countIndex) {
|
return (countIndex.toLong() shl 32) or when (countIndex) {
|
||||||
ITEM_INDEX_PINNED_STATUS -> {
|
ITEM_INDEX_PINNED_STATUS -> {
|
||||||
val status = pinnedStatuses!![position - getItemStartPosition(ITEM_INDEX_PINNED_STATUS)]
|
val status = pinnedStatuses!![position - getItemStartPosition(ITEM_INDEX_PINNED_STATUS)]
|
||||||
return (countIndex.toLong() shl 32) or status.hashCode().toLong()
|
return status.hashCode().toLong()
|
||||||
}
|
}
|
||||||
ITEM_INDEX_STATUS -> return (countIndex.toLong() shl 32) or getFieldValue(position, { cursor, indices ->
|
ITEM_INDEX_STATUS -> getFieldValue(position, { (_, accountKey, id) ->
|
||||||
val accountKey = UserKey.valueOf(cursor.getString(indices[Statuses.ACCOUNT_KEY]))
|
|
||||||
val id = cursor.getString(indices[Statuses.ID])
|
|
||||||
return@getFieldValue ParcelableStatus.calculateHashCode(accountKey, id)
|
return@getFieldValue ParcelableStatus.calculateHashCode(accountKey, id)
|
||||||
}, { status ->
|
}, { status ->
|
||||||
return@getFieldValue status.hashCode()
|
return@getFieldValue status.hashCode()
|
||||||
}, -1).toLong()
|
}, -1).toLong()
|
||||||
else -> return (countIndex.toLong() shl 32) or position.toLong()
|
else -> position.toLong()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStatusId(position: Int, raw: Boolean): String {
|
override fun getStatusId(position: Int, raw: Boolean): String {
|
||||||
return getFieldValue(position, { cursor, indices ->
|
return getFieldValue(position, { info ->
|
||||||
return@getFieldValue cursor.getString(indices[Statuses.ID])
|
return@getFieldValue info.id
|
||||||
}, { status ->
|
}, { status ->
|
||||||
return@getFieldValue status.id
|
return@getFieldValue status.id
|
||||||
}, "")
|
}, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStatusSortId(position: Int, raw: Boolean): Long {
|
fun getStatusSortId(position: Int, raw: Boolean): Long {
|
||||||
return getFieldValue(position, { cursor, indices ->
|
return getFieldValue(position, { info ->
|
||||||
return@getFieldValue cursor.safeGetLong(indices[Statuses.SORT_ID])
|
return@getFieldValue info.sortId
|
||||||
}, { status ->
|
}, { status ->
|
||||||
return@getFieldValue status.sort_id
|
return@getFieldValue status.sort_id
|
||||||
}, -1L, raw)
|
}, -1L, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStatusTimestamp(position: Int, raw: Boolean): Long {
|
override fun getStatusTimestamp(position: Int, raw: Boolean): Long {
|
||||||
return getFieldValue(position, { cursor, indices ->
|
return getFieldValue(position, { info ->
|
||||||
return@getFieldValue cursor.safeGetLong(indices[Statuses.TIMESTAMP])
|
return@getFieldValue info.timestamp
|
||||||
}, { status ->
|
}, { status ->
|
||||||
return@getFieldValue status.timestamp
|
return@getFieldValue status.timestamp
|
||||||
}, -1L)
|
}, -1L)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStatusPositionKey(position: Int, raw: Boolean): Long {
|
override fun getStatusPositionKey(position: Int, raw: Boolean): Long {
|
||||||
return getFieldValue(position, { cursor, indices ->
|
return getFieldValue(position, { info ->
|
||||||
val positionKey = cursor.safeGetLong(indices[Statuses.POSITION_KEY])
|
if (info.positionKey > 0) return@getFieldValue info.positionKey
|
||||||
if (positionKey > 0) return@getFieldValue positionKey
|
return@getFieldValue info.timestamp
|
||||||
return@getFieldValue cursor.safeGetLong(indices[Statuses.TIMESTAMP])
|
|
||||||
}, { status ->
|
}, { status ->
|
||||||
val positionKey = status.position_key
|
val positionKey = status.position_key
|
||||||
if (positionKey > 0) return@getFieldValue positionKey
|
if (positionKey > 0) return@getFieldValue positionKey
|
||||||
|
@ -261,8 +258,8 @@ abstract class ParcelableStatusesAdapter(
|
||||||
|
|
||||||
override fun getAccountKey(position: Int, raw: Boolean): UserKey {
|
override fun getAccountKey(position: Int, raw: Boolean): UserKey {
|
||||||
val def: UserKey? = null
|
val def: UserKey? = null
|
||||||
return getFieldValue(position, { cursor, indices ->
|
return getFieldValue(position, { info ->
|
||||||
return@getFieldValue UserKey.valueOf(cursor.getString(indices[Statuses.ACCOUNT_KEY]))
|
return@getFieldValue info.accountKey
|
||||||
}, { status ->
|
}, { status ->
|
||||||
return@getFieldValue status.account_key
|
return@getFieldValue status.account_key
|
||||||
}, def, raw)!!
|
}, def, raw)!!
|
||||||
|
@ -422,18 +419,31 @@ abstract class ParcelableStatusesAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <T> getFieldValue(position: Int,
|
private inline fun <T> getFieldValue(position: Int,
|
||||||
readCursorValueAction: (cursor: Cursor, indices: ObjectCursor.CursorIndices<ParcelableStatus>) -> T,
|
readInfoValueAction: (StatusInfo) -> T,
|
||||||
readStatusValueAction: (status: ParcelableStatus) -> T,
|
readStatusValueAction: (status: ParcelableStatus) -> T,
|
||||||
defValue: T, raw: Boolean = false): T {
|
defValue: T, raw: Boolean = false): T {
|
||||||
|
val data = this.data
|
||||||
if (data is ObjectCursor) {
|
if (data is ObjectCursor) {
|
||||||
val dataPosition = position - statusStartIndex
|
val dataPosition = position - statusStartIndex
|
||||||
if (dataPosition < 0 || dataPosition >= getStatusCount(true)) {
|
if (dataPosition < 0 || dataPosition >= getStatusCount(true)) {
|
||||||
throw CursorIndexOutOfBoundsException("index: $position, valid range is $0..${getStatusCount(true)}")
|
throw CursorIndexOutOfBoundsException("index: $position, valid range is $0..${getStatusCount(true)}")
|
||||||
}
|
}
|
||||||
val cursor = (data as ObjectCursor).cursor
|
val cursor = data.cursor
|
||||||
if (!cursor.safeMoveToPosition(dataPosition)) return defValue
|
if (!cursor.safeMoveToPosition(dataPosition)) return defValue
|
||||||
val indices = (data as ObjectCursor).indices
|
val indices = data.indices
|
||||||
return readCursorValueAction(cursor, indices)
|
val info = infoCache?.get(dataPosition) ?: run {
|
||||||
|
val _id = cursor.safeGetLong(indices[Statuses._ID])
|
||||||
|
val accountKey = UserKey.valueOf(cursor.getString(indices[Statuses.ACCOUNT_KEY]))
|
||||||
|
val id = cursor.getString(indices[Statuses.ID])
|
||||||
|
val timestamp = cursor.safeGetLong(indices[Statuses.TIMESTAMP])
|
||||||
|
val sortId = cursor.safeGetLong(indices[Statuses.SORT_ID])
|
||||||
|
val positionKey = cursor.safeGetLong(indices[Statuses.POSITION_KEY])
|
||||||
|
val gap = cursor.getInt(indices[Statuses.IS_GAP]) == 1
|
||||||
|
val newInfo = StatusInfo(_id, accountKey, id, timestamp, sortId, positionKey, gap)
|
||||||
|
infoCache?.set(dataPosition, newInfo)
|
||||||
|
return@run newInfo
|
||||||
|
}
|
||||||
|
return readInfoValueAction(info)
|
||||||
}
|
}
|
||||||
return readStatusValueAction(getStatus(position, raw))
|
return readStatusValueAction(getStatus(position, raw))
|
||||||
}
|
}
|
||||||
|
@ -474,6 +484,18 @@ abstract class ParcelableStatusesAdapter(
|
||||||
itemCounts[ITEM_INDEX_LOAD_END_INDICATOR] = if (ILoadMoreSupportAdapter.END in loadMoreIndicatorPosition) 1 else 0
|
itemCounts[ITEM_INDEX_LOAD_END_INDICATOR] = if (ILoadMoreSupportAdapter.END in loadMoreIndicatorPosition) 1 else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
data class StatusInfo(
|
||||||
|
val _id: Long,
|
||||||
|
val accountKey: UserKey,
|
||||||
|
val id: String,
|
||||||
|
val timestamp: Long,
|
||||||
|
val sortId: Long,
|
||||||
|
val positionKey: Long,
|
||||||
|
val gap: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VIEW_TYPE_STATUS = 2
|
const val VIEW_TYPE_STATUS = 2
|
||||||
const val VIEW_TYPE_EMPTY = 3
|
const val VIEW_TYPE_EMPTY = 3
|
||||||
|
|
Loading…
Reference in New Issue