improved status conversation load

This commit is contained in:
Mariotaku Lee 2017-02-10 19:55:00 +08:00
parent 48c7c5fa99
commit 7e577b5957
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
8 changed files with 55 additions and 47 deletions

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.fragment package org.mariotaku.twidere.fragment
import android.accounts.AccountManager import android.accounts.AccountManager
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Rect import android.graphics.Rect
@ -310,7 +309,8 @@ abstract class AbsActivitiesFragment protected constructor() :
val accountIds = arrayOf(activity.account_key) val accountIds = arrayOf(activity.account_key)
val maxIds = arrayOf(activity.min_position) val maxIds = arrayOf(activity.min_position)
val maxSortIds = longArrayOf(activity.min_sort_position) val maxSortIds = longArrayOf(activity.min_sort_position)
getActivities(BaseRefreshTaskParam(accountIds, maxIds, null, maxSortIds, null)) getActivities(BaseRefreshTaskParam(accountKeys = accountIds, maxIds = maxIds,
sinceIds = null, maxSortIds = maxSortIds, sinceSortIds = null))
} }
override fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, position: Int) { override fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, position: Int) {

View File

@ -359,7 +359,8 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
val accountIds = arrayOf(status.account_key) val accountIds = arrayOf(status.account_key)
val maxIds = arrayOf<String?>(status.id) val maxIds = arrayOf<String?>(status.id)
val maxSortIds = longArrayOf(status.sort_id) val maxSortIds = longArrayOf(status.sort_id)
getStatuses(BaseRefreshTaskParam(accountIds, maxIds, null, maxSortIds, null)) getStatuses(BaseRefreshTaskParam(accountKeys = accountIds, maxIds = maxIds, sinceIds = null,
maxSortIds = maxSortIds, sinceSortIds = null))
} }
override fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, statusPosition: Int) { override fun onMediaClick(holder: IStatusViewHolder, view: View, media: ParcelableMedia, statusPosition: Int) {

View File

@ -8,6 +8,7 @@ import org.mariotaku.kpreferences.get
import org.mariotaku.sqliteqb.library.OrderBy import org.mariotaku.sqliteqb.library.OrderBy
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.MessagesEntriesAdapter import org.mariotaku.twidere.adapter.MessagesEntriesAdapter
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
import org.mariotaku.twidere.constant.newDocumentApiKey import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.extension.model.user import org.mariotaku.twidere.extension.model.user
import org.mariotaku.twidere.loader.ObjectCursorLoader import org.mariotaku.twidere.loader.ObjectCursorLoader
@ -35,6 +36,7 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
adapter.listener = this adapter.listener = this
adapter.loadMoreSupportedPosition = ILoadMoreSupportAdapter.END
loaderManager.initLoader(0, null, this) loaderManager.initLoader(0, null, this)
} }
@ -70,6 +72,10 @@ class MessagesEntriesFragment : AbsContentListRecyclerViewFragment<MessagesEntri
return true return true
} }
override fun onLoadMoreContents(position: Long) {
super.onLoadMoreContents(position)
}
override fun onConversationClick(position: Int) { override fun onConversationClick(position: Int) {
val conversation = adapter.getConversation(position) ?: return val conversation = adapter.getConversation(position) ?: return
IntentUtils.openMessageConversation(context, conversation.account_key, conversation.id) IntentUtils.openMessageConversation(context, conversation.account_key, conversation.id)

View File

@ -155,7 +155,9 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
val loader = ConversationLoader(activity, status, sinceId, maxId, sinceSortId, maxSortId, val loader = ConversationLoader(activity, status, sinceId, maxId, sinceSortId, maxSortId,
adapter.getData(), true, loadingMore) adapter.getData(), true, loadingMore)
// Setting comparator to null lets statuses sort ascending // Setting comparator to null lets statuses sort ascending
loader.comparator = null loader.comparator = Comparator { l, r ->
(l.sort_id - r.sort_id).toInt()
}
return loader return loader
} }
@ -1503,7 +1505,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
override val lightFont: Boolean override val lightFont: Boolean
override val mediaPreviewEnabled: Boolean override val mediaPreviewEnabled: Boolean
override val sensitiveContentEnabled: Boolean override val sensitiveContentEnabled: Boolean
private val mShowCardActions: Boolean private val showCardActions: Boolean
override val useStarsForLikes: Boolean override val useStarsForLikes: Boolean
private var mDetailMediaExpanded: Boolean = false private var mDetailMediaExpanded: Boolean = false
@ -1533,8 +1535,8 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
private var data: List<ParcelableStatus>? = null private var data: List<ParcelableStatus>? = null
private var replyError: CharSequence? = null private var replyError: CharSequence? = null
private var conversationError: CharSequence? = null private var conversationError: CharSequence? = null
private var mReplyStart: Int = 0 private var replyStart: Int = 0
private var mShowingActionCardPosition: Int = 0 private var showingActionCardPosition: Int = 0
init { init {
setHasStableIds(true) setHasStableIds(true)
@ -1555,7 +1557,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
linkHighlightingStyle = preferences[linkHighlightOptionKey] linkHighlightingStyle = preferences[linkHighlightOptionKey]
mediaPreviewEnabled = preferences[mediaPreviewKey] mediaPreviewEnabled = preferences[mediaPreviewKey]
sensitiveContentEnabled = preferences.getBoolean(SharedPreferenceConstants.KEY_DISPLAY_SENSITIVE_CONTENTS, false) sensitiveContentEnabled = preferences.getBoolean(SharedPreferenceConstants.KEY_DISPLAY_SENSITIVE_CONTENTS, false)
mShowCardActions = !preferences[hideCardActionsKey] showCardActions = !preferences[hideCardActionsKey]
useStarsForLikes = preferences[iWantMyStarsBackKey] useStarsForLikes = preferences[iWantMyStarsBackKey]
val listener = StatusAdapterLinkClickHandler<List<ParcelableStatus>>(context, preferences) val listener = StatusAdapterLinkClickHandler<List<ParcelableStatus>>(context, preferences)
listener.setAdapter(this) listener.setAdapter(this)
@ -1570,9 +1572,9 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
return data!![position - getIndexStart(ITEM_IDX_CONVERSATION)] return data!![position - getIndexStart(ITEM_IDX_CONVERSATION)]
} }
ITEM_IDX_REPLY -> { ITEM_IDX_REPLY -> {
if (data == null || mReplyStart < 0) return null if (data == null || replyStart < 0) return null
return data!![position - getIndexStart(ITEM_IDX_CONVERSATION) return data!![position - getIndexStart(ITEM_IDX_CONVERSATION)
- getTypeCount(ITEM_IDX_CONVERSATION) - getTypeCount(ITEM_IDX_STATUS) + mReplyStart] - getTypeCount(ITEM_IDX_CONVERSATION) - getTypeCount(ITEM_IDX_STATUS) + replyStart]
} }
ITEM_IDX_STATUS -> { ITEM_IDX_STATUS -> {
return status return status
@ -1622,15 +1624,15 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
} }
override fun isCardActionsShown(position: Int): Boolean { override fun isCardActionsShown(position: Int): Boolean {
if (position == RecyclerView.NO_POSITION) return mShowCardActions if (position == RecyclerView.NO_POSITION) return showCardActions
return mShowCardActions || mShowingActionCardPosition == position return showCardActions || showingActionCardPosition == position
} }
override fun showCardActions(position: Int) { override fun showCardActions(position: Int) {
if (mShowingActionCardPosition != RecyclerView.NO_POSITION) { if (showingActionCardPosition != RecyclerView.NO_POSITION) {
notifyItemChanged(mShowingActionCardPosition) notifyItemChanged(showingActionCardPosition)
} }
mShowingActionCardPosition = position showingActionCardPosition = position
if (position != RecyclerView.NO_POSITION) { if (position != RecyclerView.NO_POSITION) {
notifyItemChanged(position) notifyItemChanged(position)
} }
@ -1638,12 +1640,12 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
override fun setData(data: List<ParcelableStatus>?): Boolean { override fun setData(data: List<ParcelableStatus>?): Boolean {
val status = this.status ?: return false val status = this.status ?: return false
val changed = !CompareUtils.objectEquals(data, data) val changed = this.data != data
this.data = data this.data = data
if (data == null || data.isEmpty()) { if (data == null || data.isEmpty()) {
setTypeCount(ITEM_IDX_CONVERSATION, 0) setTypeCount(ITEM_IDX_CONVERSATION, 0)
setTypeCount(ITEM_IDX_REPLY, 0) setTypeCount(ITEM_IDX_REPLY, 0)
mReplyStart = -1 replyStart = -1
} else { } else {
var sortId = status.sort_id var sortId = status.sort_id
if (status.is_retweet) { if (status.is_retweet) {
@ -1657,8 +1659,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
var conversationCount = 0 var conversationCount = 0
var replyCount = 0 var replyCount = 0
var replyStart = -1 var replyStart = -1
for (i in 0 until data.size) { data.forEachIndexed { i, item ->
val item = data[i]
if (item.sort_id < sortId) { if (item.sort_id < sortId) {
conversationCount++ conversationCount++
} else if (item.sort_id > sortId && status.id != item.id) { } else if (item.sort_id > sortId && status.id != item.id) {
@ -1670,7 +1671,7 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
} }
setTypeCount(ITEM_IDX_CONVERSATION, conversationCount) setTypeCount(ITEM_IDX_CONVERSATION, conversationCount)
setTypeCount(ITEM_IDX_REPLY, replyCount) setTypeCount(ITEM_IDX_REPLY, replyCount)
mReplyStart = replyStart this.replyStart = replyStart
} }
notifyDataSetChanged() notifyDataSetChanged()
updateItemDecoration() updateItemDecoration()

View File

@ -7,15 +7,11 @@ open class BaseRefreshTaskParam(
override val accountKeys: Array<UserKey>, override val accountKeys: Array<UserKey>,
override val maxIds: Array<String?>?, override val maxIds: Array<String?>?,
override val sinceIds: Array<String?>?, override val sinceIds: Array<String?>?,
override val cursors: Array<String?>? = null,
override val maxSortIds: LongArray? = null, override val maxSortIds: LongArray? = null,
override val sinceSortIds: LongArray? = null override val sinceSortIds: LongArray? = null
) : RefreshTaskParam { ) : RefreshTaskParam {
override var isLoadingMore: Boolean = false override var isLoadingMore: Boolean = false
override var shouldAbort: Boolean = false override var shouldAbort: Boolean = false
override val hasMaxIds: Boolean
get() = maxIds != null
override val hasSinceIds: Boolean
get() = sinceIds != null
} }

View File

@ -10,13 +10,20 @@ interface RefreshTaskParam {
val sinceIds: Array<String?>? val sinceIds: Array<String?>?
val cursors: Array<String?>?
val maxSortIds: LongArray? val maxSortIds: LongArray?
val sinceSortIds: LongArray? val sinceSortIds: LongArray?
val hasMaxIds: Boolean val hasMaxIds: Boolean
get() = maxIds != null
val hasSinceIds: Boolean val hasSinceIds: Boolean
get() = sinceIds != null
val hasCursors: Boolean
get() = cursors != null
val isLoadingMore: Boolean val isLoadingMore: Boolean

View File

@ -22,11 +22,8 @@ abstract class SimpleRefreshTaskParam : RefreshTaskParam {
override val sinceIds: Array<String?>? override val sinceIds: Array<String?>?
get() = null get() = null
override val hasMaxIds: Boolean override val cursors: Array<String?>?
get() = maxIds != null get() = null
override val hasSinceIds: Boolean
get() = sinceIds != null
override val sinceSortIds: LongArray? override val sinceSortIds: LongArray?
get() = null get() = null

View File

@ -20,7 +20,6 @@ import org.mariotaku.twidere.model.util.AccountUtils.getAccountDetails
import org.mariotaku.twidere.model.util.ParcelableMessageUtils import org.mariotaku.twidere.model.util.ParcelableMessageUtils
import org.mariotaku.twidere.model.util.ParcelableUserUtils import org.mariotaku.twidere.model.util.ParcelableUserUtils
import org.mariotaku.twidere.model.util.UserKeyUtils import org.mariotaku.twidere.model.util.UserKeyUtils
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns
import org.mariotaku.twidere.provider.TwidereDataStore.Messages import org.mariotaku.twidere.provider.TwidereDataStore.Messages
import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations
import org.mariotaku.twidere.util.content.ContentResolverUtils import org.mariotaku.twidere.util.content.ContentResolverUtils
@ -37,7 +36,7 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
val details = getAccountDetails(am, accountKey, true) ?: return@forEachIndexed val details = getAccountDetails(am, accountKey, true) ?: return@forEachIndexed
val microBlog = details.newMicroBlogInstance(context, true, cls = MicroBlog::class.java) val microBlog = details.newMicroBlogInstance(context, true, cls = MicroBlog::class.java)
val messages = try { val messages = try {
getMessages(microBlog, details) getMessages(microBlog, details, param, i)
} catch (e: MicroBlogException) { } catch (e: MicroBlogException) {
return@forEachIndexed return@forEachIndexed
} }
@ -49,7 +48,7 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
callback?.invoke(true) callback?.invoke(true)
} }
private fun getMessages(microBlog: MicroBlog, details: AccountDetails): GetMessagesData { private fun getMessages(microBlog: MicroBlog, details: AccountDetails, param: RefreshTaskParam, index: Int): GetMessagesData {
when (details.type) { when (details.type) {
AccountType.FANFOU -> { AccountType.FANFOU -> {
// Use fanfou DM api // Use fanfou DM api
@ -58,32 +57,37 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
AccountType.TWITTER -> { AccountType.TWITTER -> {
// Use official DM api // Use official DM api
if (details.isOfficial(context)) { if (details.isOfficial(context)) {
return getTwitterOfficialMessages(microBlog, details) return getTwitterOfficialMessages(microBlog, details, param, index)
} }
} }
} }
// Use default method // Use default method
return getDefaultMessages(microBlog, details) return getDefaultMessages(microBlog, details, param, index)
} }
private fun getFanfouMessages(microBlog: MicroBlog): GetMessagesData { private fun getFanfouMessages(microBlog: MicroBlog): GetMessagesData {
return GetMessagesData(emptyList(), emptyList()) return GetMessagesData(emptyList(), emptyList())
} }
private fun getTwitterOfficialMessages(microBlog: MicroBlog, details: AccountDetails): GetMessagesData { private fun getTwitterOfficialMessages(microBlog: MicroBlog, details: AccountDetails, param: RefreshTaskParam, index: Int): GetMessagesData {
return getDefaultMessages(microBlog, details) return getDefaultMessages(microBlog, details, param, index)
} }
private fun getDefaultMessages(microBlog: MicroBlog, details: AccountDetails): GetMessagesData { private fun getDefaultMessages(microBlog: MicroBlog, details: AccountDetails, param: RefreshTaskParam, index: Int): GetMessagesData {
val accountKey = details.key val accountKey = details.key
val paging = Paging()
val received = microBlog.getDirectMessages(Paging().apply {
count(100)
})
val sent = microBlog.getSentDirectMessages(Paging().apply {
count(100)
})
val insertMessages = arrayListOf<ParcelableMessage>() val insertMessages = arrayListOf<ParcelableMessage>()
val conversations = hashMapOf<String, ParcelableMessageConversation>() val conversations = hashMapOf<String, ParcelableMessageConversation>()
val received = microBlog.getDirectMessages(paging)
val sent = microBlog.getSentDirectMessages(paging)
val conversationIds = hashSetOf<String>() val conversationIds = hashSetOf<String>()
received.forEach { received.forEach {
conversationIds.add(ParcelableMessageUtils.incomingConversationId(it.senderId, it.recipientId)) conversationIds.add(ParcelableMessageUtils.incomingConversationId(it.senderId, it.recipientId))
@ -135,10 +139,6 @@ class GetMessagesTask(context: Context) : BaseAbstractTask<RefreshTaskParam, Uni
private fun storeMessages(data: GetMessagesData, details: AccountDetails) { private fun storeMessages(data: GetMessagesData, details: AccountDetails) {
val resolver = context.contentResolver val resolver = context.contentResolver
val where = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY).sql
val whereArgs = arrayOf(details.key.toString())
resolver.delete(Messages.CONTENT_URI, where, whereArgs)
resolver.delete(Conversations.CONTENT_URI, where, whereArgs)
val conversationsValues = data.conversations.map { val conversationsValues = data.conversations.map {
val values = ParcelableMessageConversationValuesCreator.create(it) val values = ParcelableMessageConversationValuesCreator.create(it)
if (it._id > 0) { if (it._id > 0) {