mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-02 17:56:56 +01:00
implementing relationship caching
This commit is contained in:
parent
e9205dfb23
commit
0f86fc75a4
1
.gitignore
vendored
1
.gitignore
vendored
@ -29,6 +29,7 @@ Thumbs.db
|
||||
|
||||
# Local files
|
||||
/captures
|
||||
/reports
|
||||
|
||||
# JRE error dumps
|
||||
hs_err_*.log
|
@ -1,3 +1,3 @@
|
||||
org.gradle.daemon=true
|
||||
org.gradle.jvmargs=-Xms2048m -Xmx3072m
|
||||
systemProp.kotlin.daemon.verbose=true
|
||||
kotlin.incremental=true
|
@ -73,6 +73,25 @@ public class ParcelableRelationship implements Parcelable {
|
||||
|
||||
public boolean filtering;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ParcelableRelationship that = (ParcelableRelationship) o;
|
||||
|
||||
if (!account_key.equals(that.account_key)) return false;
|
||||
return user_key.equals(that.user_key);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = account_key.hashCode();
|
||||
result = 31 * result + user_key.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
@ -34,7 +34,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.mariotaku.twidere"
|
||||
minSdkVersion 14
|
||||
minSdkVersion project.properties['overrideMinSdkVersion'] ?: 14
|
||||
targetSdkVersion 25
|
||||
versionCode 301
|
||||
versionName '3.4.39'
|
||||
|
@ -39,4 +39,8 @@ inline fun <reified T> List<T>.subArray(range: IntRange): Array<T> {
|
||||
return Array(range.count()) {
|
||||
this[range.start + it]
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> T.addTo(collection: MutableCollection<T>): Boolean {
|
||||
return collection.add(this)
|
||||
}
|
@ -19,16 +19,22 @@
|
||||
|
||||
package org.mariotaku.twidere.model.util
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.support.v4.util.ArraySet
|
||||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.microblog.library.twitter.model.Relationship
|
||||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.twidere.model.ParcelableRelationship
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||
|
||||
object ParcelableRelationshipUtils {
|
||||
|
||||
fun create(accountKey: UserKey, userKey: UserKey, relationship: Relationship?,
|
||||
filtering: Boolean): ParcelableRelationship {
|
||||
filtering: Boolean): ParcelableRelationship {
|
||||
val obj = ParcelableRelationship()
|
||||
obj.account_key = accountKey
|
||||
obj.user_key = userKey
|
||||
@ -63,7 +69,7 @@ object ParcelableRelationshipUtils {
|
||||
}
|
||||
|
||||
fun create(accountKey: UserKey, userKey: UserKey, user: User,
|
||||
filtering: Boolean): ParcelableRelationship {
|
||||
filtering: Boolean = false): ParcelableRelationship {
|
||||
val obj = ParcelableRelationship()
|
||||
obj.account_key = accountKey
|
||||
obj.user_key = userKey
|
||||
@ -76,4 +82,25 @@ object ParcelableRelationshipUtils {
|
||||
obj.notifications_enabled = user.isNotificationsEnabled == true
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* @param relationships Relationships to update, if an item has _id, then we will call
|
||||
* `ContentResolver.update`, `ContentResolver.bulkInsert` otherwise.
|
||||
*/
|
||||
fun insert(cr: ContentResolver, relationships: Collection<ParcelableRelationship>) {
|
||||
val insertItems = ArraySet<ParcelableRelationship>()
|
||||
val valuesCreator = ObjectCursor.valuesCreatorFrom(ParcelableRelationship::class.java)
|
||||
relationships.forEach {
|
||||
if (it._id > 0) {
|
||||
val values = valuesCreator.create(it)
|
||||
val where = Expression.equalsArgs(CachedRelationships._ID).sql
|
||||
val whereArgs = arrayOf(it._id.toString())
|
||||
cr.update(CachedRelationships.CONTENT_URI, values, where, whereArgs)
|
||||
} else {
|
||||
insertItems.add(it)
|
||||
}
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, CachedRelationships.CONTENT_URI,
|
||||
insertItems.map(valuesCreator::create))
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class DestroyFriendshipTask(context: Context) : AbsFriendshipOperationTask(conte
|
||||
val where = Expression.and(Expression.equalsArgs(Statuses.ACCOUNT_KEY),
|
||||
Expression.or(Expression.equalsArgs(Statuses.USER_KEY),
|
||||
Expression.equalsArgs(Statuses.RETWEETED_BY_USER_KEY)))
|
||||
val whereArgs = arrayOf(args.userKey.toString(), args.userKey.toString(), args.userKey.toString())
|
||||
val whereArgs = arrayOf(args.accountKey.toString(), args.userKey.toString(), args.userKey.toString())
|
||||
val resolver = context.contentResolver
|
||||
resolver.delete(Statuses.CONTENT_URI, where.sql, whereArgs)
|
||||
}
|
||||
|
68
twidere/src/main/kotlin/org/mariotaku/twidere/task/cache/CacheUserRelationshipTask.kt
vendored
Normal file
68
twidere/src/main/kotlin/org/mariotaku/twidere/task/cache/CacheUserRelationshipTask.kt
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
package org.mariotaku.twidere.task.cache
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.support.v4.util.ArraySet
|
||||
import org.mariotaku.abstask.library.AbstractTask
|
||||
import org.mariotaku.ktextension.map
|
||||
import org.mariotaku.ktextension.useCursor
|
||||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.sqliteqb.library.Expression
|
||||
import org.mariotaku.twidere.model.ParcelableRelationship
|
||||
import org.mariotaku.twidere.model.ParcelableUser
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.model.util.ParcelableRelationshipUtils
|
||||
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
||||
import org.mariotaku.twidere.model.util.UserKeyUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships
|
||||
import org.mariotaku.twidere.task.BaseAbstractTask
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||
|
||||
/**
|
||||
* Created by Mariotaku on 2017/3/17.
|
||||
*/
|
||||
|
||||
class CacheUserRelationshipTask(context: Context, val accountKey: UserKey, val users: Collection<User>) : BaseAbstractTask<Any?, Unit, Any?>(context) {
|
||||
override fun doLongOperation(param: Any?) {
|
||||
cacheUserRelationships(context.contentResolver, accountKey, users)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun cacheUserRelationships(cr: ContentResolver, accountKey: UserKey, users: Collection<User>) {
|
||||
|
||||
val parcelableUsers = users.map { ParcelableUserUtils.fromUser(it, accountKey) }
|
||||
|
||||
val userValuesCreator = ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java)
|
||||
ContentResolverUtils.bulkInsert(cr, CachedUsers.CONTENT_URI, parcelableUsers.map(userValuesCreator::create))
|
||||
|
||||
val selectionArgsList = parcelableUsers.mapTo(mutableListOf(accountKey.toString())) {
|
||||
it.key.toString()
|
||||
}
|
||||
@SuppressLint("Recycle")
|
||||
val localRelationships = cr.query(CachedRelationships.CONTENT_URI, CachedRelationships.COLUMNS,
|
||||
Expression.and(Expression.equalsArgs(CachedRelationships.ACCOUNT_KEY),
|
||||
Expression.inArgs(CachedRelationships.USER_KEY, users.size)).sql,
|
||||
selectionArgsList.toTypedArray(), null).useCursor { cur ->
|
||||
return@useCursor cur.map(ObjectCursor.indicesFrom(cur, ParcelableRelationship::class.java))
|
||||
}
|
||||
val relationships = users.mapTo(ArraySet<ParcelableRelationship>()) { user ->
|
||||
val userKey = UserKeyUtils.fromUser(user)
|
||||
return@mapTo localRelationships.find {
|
||||
it.user_key == userKey
|
||||
}?.apply {
|
||||
user.isFollowing?.let { this.following = it }
|
||||
user.isFollowedBy?.let { this.followed_by = it }
|
||||
user.isBlocking?.let { this.blocking = it }
|
||||
user.isBlockedBy?.let { this.blocked_by = it }
|
||||
user.isMuting?.let { this.muting = it }
|
||||
user.isNotificationsEnabled?.let { this.notifications_enabled = it }
|
||||
} ?: ParcelableRelationshipUtils.create(accountKey, userKey, user)
|
||||
}
|
||||
ParcelableRelationshipUtils.insert(cr, relationships)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -17,14 +17,17 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.task
|
||||
package org.mariotaku.twidere.task.cache
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import com.twitter.Extractor
|
||||
import org.mariotaku.abstask.library.AbstractTask
|
||||
import org.mariotaku.ktextension.addTo
|
||||
import org.mariotaku.microblog.library.twitter.model.Status
|
||||
import org.mariotaku.microblog.library.twitter.model.User
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.model.UserKey
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.*
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator
|
||||
import org.mariotaku.twidere.util.InternalTwitterContentUtils
|
||||
@ -33,28 +36,28 @@ import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||
import java.util.*
|
||||
|
||||
class CacheUsersStatusesTask(
|
||||
private val context: Context
|
||||
) : AbstractTask<TwitterListResponse<Status>, Unit?, Unit?>() {
|
||||
private val context: Context,
|
||||
private val accountKey: UserKey,
|
||||
private val statuses: List<Status>
|
||||
) : AbstractTask<Any?, Unit?, Unit?>() {
|
||||
|
||||
private val profileImageSize = context.getString(R.string.profile_image_size)
|
||||
|
||||
override fun doLongOperation(params: TwitterListResponse<Status>) {
|
||||
override fun doLongOperation(params: Any?) {
|
||||
val resolver = context.contentResolver
|
||||
val extractor = Extractor()
|
||||
val list = params.data ?: return
|
||||
var bulkIdx = 0
|
||||
val totalSize = list.size
|
||||
val totalSize = statuses.size
|
||||
while (bulkIdx < totalSize) {
|
||||
var idx = bulkIdx
|
||||
val end = Math.min(totalSize, bulkIdx + ContentResolverUtils.MAX_BULK_COUNT)
|
||||
while (idx < end) {
|
||||
val status = list[idx]
|
||||
val status = statuses[idx]
|
||||
|
||||
val usersValues = HashSet<ContentValues>()
|
||||
val users = HashSet<User>()
|
||||
val statusesValues = HashSet<ContentValues>()
|
||||
val hashTagValues = HashSet<ContentValues>()
|
||||
|
||||
val accountKey = params.accountKey
|
||||
statusesValues.add(ContentValuesCreator.createStatus(status, accountKey, profileImageSize))
|
||||
val text = InternalTwitterContentUtils.unescapeTwitterStatusText(status.extendedText)
|
||||
for (hashtag in extractor.extractHashtags(text)) {
|
||||
@ -62,19 +65,14 @@ class CacheUsersStatusesTask(
|
||||
values.put(CachedHashtags.NAME, hashtag)
|
||||
hashTagValues.add(values)
|
||||
}
|
||||
val cachedUser = ContentValuesCreator.createCachedUser(status.user)
|
||||
cachedUser.put(CachedUsers.LAST_SEEN, System.currentTimeMillis())
|
||||
usersValues.add(cachedUser)
|
||||
if (status.isRetweet) {
|
||||
val cachedRetweetedUser = ContentValuesCreator.createCachedUser(status.retweetedStatus.user,
|
||||
profileImageSize)
|
||||
cachedRetweetedUser.put(CachedUsers.LAST_SEEN, System.currentTimeMillis())
|
||||
usersValues.add(cachedRetweetedUser)
|
||||
}
|
||||
|
||||
status.user?.addTo(users)
|
||||
status.retweetedStatus?.user?.addTo(users)
|
||||
status.quotedStatus?.user?.addTo(users)
|
||||
|
||||
ContentResolverUtils.bulkInsert(resolver, CachedStatuses.CONTENT_URI, statusesValues)
|
||||
ContentResolverUtils.bulkInsert(resolver, CachedHashtags.CONTENT_URI, hashTagValues)
|
||||
ContentResolverUtils.bulkInsert(resolver, CachedUsers.CONTENT_URI, usersValues)
|
||||
CacheUserRelationshipTask.cacheUserRelationships(resolver, accountKey, users)
|
||||
idx++
|
||||
}
|
||||
bulkIdx += 100
|
@ -33,7 +33,7 @@ import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses
|
||||
import org.mariotaku.twidere.task.BaseAbstractTask
|
||||
import org.mariotaku.twidere.task.CacheUsersStatusesTask
|
||||
import org.mariotaku.twidere.task.cache.CacheUsersStatusesTask
|
||||
import org.mariotaku.twidere.util.*
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||
import java.util.*
|
||||
@ -109,12 +109,10 @@ abstract class GetStatusesTask(
|
||||
val storeResult = storeStatus(accountKey, details, statuses, sinceId, maxId, sinceSortId,
|
||||
maxSortId, loadItemLimit, false)
|
||||
// TODO cache related data and preload
|
||||
val cacheTask = CacheUsersStatusesTask(context)
|
||||
val response = TwitterWrapper.StatusListResponse(accountKey, statuses)
|
||||
cacheTask.params = response
|
||||
val cacheTask = CacheUsersStatusesTask(context, accountKey, statuses)
|
||||
TaskStarter.execute(cacheTask)
|
||||
errorInfoStore.remove(errorInfoKey, accountKey.id)
|
||||
result.add(response)
|
||||
result.add(TwitterWrapper.StatusListResponse(accountKey, statuses))
|
||||
if (storeResult != 0) {
|
||||
throw GetTimelineException(storeResult)
|
||||
}
|
||||
|
@ -34,10 +34,8 @@ import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches
|
||||
object ContentValuesCreator {
|
||||
|
||||
fun createCachedUser(user: User, profileImageSize: String = "normal"): ContentValues {
|
||||
val values = ContentValues()
|
||||
ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java).writeTo(ParcelableUserUtils.fromUser(user, null,
|
||||
profileImageSize = profileImageSize), values)
|
||||
return values
|
||||
return ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java)
|
||||
.create(ParcelableUserUtils.fromUser(user, null, profileImageSize = profileImageSize))
|
||||
}
|
||||
|
||||
fun createFilteredUser(status: ParcelableStatus): ContentValues {
|
||||
|
Loading…
x
Reference in New Issue
Block a user