improved database performance

fixed auto complete hashtag icon
This commit is contained in:
Mariotaku Lee 2015-04-02 00:09:19 +08:00
parent dd729d2d5c
commit fe5a6eb6c6
21 changed files with 157 additions and 141 deletions

View File

@ -35,7 +35,7 @@ import static android.text.TextUtils.isEmpty;
public class ContentResolverUtils {
private static final int MAX_DELETE_COUNT = 128;
public static final int MAX_BULK_COUNT = 128;
public static <T> int bulkDelete(final ContentResolver resolver, final Uri uri, final String inColumn,
final Collection<T> colValues, final String extraWhere, final boolean valuesIsString) {
@ -47,10 +47,10 @@ public class ContentResolverUtils {
final T[] colValues, final String extraWhere, final boolean valuesIsString) {
if (resolver == null || uri == null || isEmpty(inColumn) || colValues == null || colValues.length == 0)
return 0;
final int col_values_length = colValues.length, blocks_count = col_values_length / MAX_DELETE_COUNT + 1;
final int col_values_length = colValues.length, blocks_count = col_values_length / MAX_BULK_COUNT + 1;
int rows_deleted = 0;
for (int i = 0; i < blocks_count; i++) {
final int start = i * MAX_DELETE_COUNT, end = Math.min(start + MAX_DELETE_COUNT, col_values_length);
final int start = i * MAX_BULK_COUNT, end = Math.min(start + MAX_BULK_COUNT, col_values_length);
final String[] block = TwidereArrayUtils.toStringArray(TwidereArrayUtils.subArray(colValues, start, end));
if (valuesIsString) {
final StringBuilder where = new StringBuilder(inColumn + " IN(" + TwidereArrayUtils.toStringForSQL(block)
@ -78,10 +78,10 @@ public class ContentResolverUtils {
public static int bulkInsert(final ContentResolver resolver, final Uri uri, final ContentValues[] values) {
if (resolver == null || uri == null || values == null || values.length == 0) return 0;
final int colValuesLength = values.length, blocksCount = colValuesLength / MAX_DELETE_COUNT + 1;
final int colValuesLength = values.length, blocksCount = colValuesLength / MAX_BULK_COUNT + 1;
int rowsInserted = 0;
for (int i = 0; i < blocksCount; i++) {
final int start = i * MAX_DELETE_COUNT, end = Math.min(start + MAX_DELETE_COUNT, colValuesLength);
final int start = i * MAX_BULK_COUNT, end = Math.min(start + MAX_BULK_COUNT, colValuesLength);
final ContentValues[] block = new ContentValues[end - start];
System.arraycopy(values, start, block, 0, end - start);
rowsInserted += resolver.bulkInsert(uri, block);

View File

@ -129,6 +129,12 @@ public class Expression implements SQLLang {
}
public static Expression like(final Column column, final SQLLang expression) {
return new Expression(String.format(Locale.ROOT, "%s LIKE %s", column.getSQL(), expression.getSQL()));
}
public static Expression likeRaw(final Column column, final String pattern) {
return new Expression(String.format(Locale.ROOT, "%s LIKE %s", column.getSQL(), pattern));
}

View File

@ -38,6 +38,7 @@ import org.mariotaku.querybuilder.query.SQLDropTriggerQuery;
import org.mariotaku.querybuilder.query.SQLDropViewQuery;
import org.mariotaku.querybuilder.query.SQLInsertQuery;
import org.mariotaku.querybuilder.query.SQLSelectQuery;
import org.mariotaku.querybuilder.query.SQLUpdateQuery;
public class SQLQueryBuilder {
@ -105,6 +106,10 @@ public class SQLQueryBuilder {
return new SQLInsertQuery.Builder().insertInto(onConflict, table);
}
public static SQLUpdateQuery.Builder update(final OnConflict onConflict, final Table table) {
return new SQLUpdateQuery.Builder().update(onConflict, table);
}
public static SQLInsertQuery.Builder insertInto(final String table) {
return insertInto(null, table);
}

View File

@ -8,9 +8,9 @@ import java.util.Locale;
public class SetValue implements SQLLang {
private final Columns.Column column;
private final Expression expression;
private final SQLLang expression;
public SetValue(Columns.Column column, Expression expression) {
public SetValue(Columns.Column column, SQLLang expression) {
this.column = column;
this.expression = expression;
}

View File

@ -4,6 +4,7 @@ import org.mariotaku.querybuilder.Expression;
import org.mariotaku.querybuilder.OnConflict;
import org.mariotaku.querybuilder.SQLQuery;
import org.mariotaku.querybuilder.SetValue;
import org.mariotaku.querybuilder.Table;
import org.mariotaku.querybuilder.Utils;
import java.util.Locale;
@ -11,7 +12,7 @@ import java.util.Locale;
public class SQLUpdateQuery implements SQLQuery {
private OnConflict onConflict;
private String table;
private Table table;
private SetValue[] values;
private Expression where;
@ -27,7 +28,7 @@ public class SQLUpdateQuery implements SQLQuery {
if (onConflict != null) {
sb.append(String.format(Locale.ROOT, "OR %s ", onConflict.getAction()));
}
sb.append(String.format(Locale.ROOT, "%s ", table));
sb.append(String.format(Locale.ROOT, "%s ", table.getSQL()));
sb.append(String.format(Locale.ROOT, "SET %s ", Utils.toString(values, ',', false)));
if (where != null) {
sb.append(String.format(Locale.ROOT, "WHERE %s ", where.getSQL()));
@ -47,7 +48,7 @@ public class SQLUpdateQuery implements SQLQuery {
this.onConflict = onConflict;
}
void setTable(final String table) {
void setTable(final Table table) {
this.table = table;
}
@ -80,14 +81,14 @@ public class SQLUpdateQuery implements SQLQuery {
return this;
}
public Builder update(final OnConflict onConflict, final String table) {
public Builder update(final OnConflict onConflict, final Table table) {
checkNotBuilt();
query.setOnConflict(onConflict);
query.setTable(table);
return this;
}
public Builder update(final String table) {
public Builder update(final Table table) {
return update(null, table);
}

View File

@ -23,9 +23,10 @@
<application>
<activity
tools:replace="android:label"
android:name="im.dino.dbinspector.activities.DbInspectorActivity"
android:label="Database Inspector">
android:exported="false"
android:label="Database Inspector"
tools:replace="android:label">
<intent-filter tools:node="removeAll">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>

View File

@ -33,7 +33,7 @@ import static org.mariotaku.twidere.annotation.Preference.Type.STRING;
public interface Constants extends TwidereConstants {
String DATABASES_NAME = "twidere.sqlite";
int DATABASES_VERSION = 90;
int DATABASES_VERSION = 92;
int MENU_GROUP_STATUS_EXTENSION = 10;
int MENU_GROUP_COMPOSE_EXTENSION = 11;

View File

@ -24,6 +24,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.PorterDuff.Mode;
import android.support.annotation.NonNull;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
@ -118,8 +119,10 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
mProfileImageLoader.cancelDisplayTask(icon);
// icon.setImageResource(R.drawable.ic_profile_image_default);
}
icon.clearColorFilter();
} else {
icon.setImageResource(R.drawable.ic_action_hashtag);
icon.setColorFilter(text1.getCurrentTextColor(), Mode.SRC_ATOP);
}
super.bindView(view, context, cursor);
}

View File

@ -201,6 +201,10 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
return getArguments().getString(EXTRA_QUERY);
}
public long getAccountId() {
return getArguments().getLong(EXTRA_ACCOUNT_ID);
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.menu_search, menu);
@ -223,9 +227,7 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
final AsyncTwitterWrapper twitter = getTwitterWrapper();
final Bundle args = getArguments();
if (twitter != null && args != null) {
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final String query = args.getString(EXTRA_QUERY);
twitter.createSavedSearchAsync(accountId, query);
twitter.createSavedSearchAsync(getAccountId(), getQuery());
}
return true;
}
@ -233,6 +235,7 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
final Intent intent = new Intent(getActivity(), ComposeActivity.class);
intent.setAction(INTENT_ACTION_COMPOSE);
intent.putExtra(Intent.EXTRA_TEXT, String.format("#%s ", getQuery()));
intent.putExtra(EXTRA_ACCOUNT_ID, getAccountId());
startActivity(intent);
break;
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -50,8 +51,9 @@ public class MediaTimelineLoader extends Twitter4JStatusesLoader {
mIsMyTimeline = userId > 0 ? accountId == userId : accountId == getAccountId(context, screenName);
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(final Twitter twitter, final Paging paging) throws TwitterException {
protected ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
if (twitter == null) return null;
if (mUserId != -1)
return twitter.getMediaTimeline(mUserId, paging);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -49,8 +50,9 @@ public class RetweetsOfMeLoader extends Twitter4JStatusesLoader {
return mTotalItemsCount;
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(final Twitter twitter, final Paging paging) throws TwitterException {
protected ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
if (twitter == null) return null;
final ResponseList<Status> statuses = twitter.getRetweetsOfMe(paging);
if (mTotalItemsCount == -1 && !statuses.isEmpty()) {

View File

@ -20,6 +20,7 @@
package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -45,8 +46,9 @@ public class StatusRepliesLoader extends UserMentionsLoader {
mInReplyToStatusId = statusId;
}
@NonNull
@Override
public List<Status> getStatuses(final Twitter twitter, final Paging paging) throws TwitterException {
public List<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
final Context context = getContext();
final List<Status> result = new ArrayList<>();
if (shouldForceUsingPrivateAPIs(context) || isOfficialTwitterInstance(context, twitter)) {

View File

@ -22,7 +22,6 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
@ -30,8 +29,6 @@ import android.util.Log;
import org.mariotaku.jsonserializer.JSONFileIO;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.task.CacheUsersStatusesTask;
import org.mariotaku.twidere.util.TwitterWrapper.StatusListResponse;
import java.io.File;
import java.io.IOException;
@ -55,7 +52,6 @@ public abstract class Twitter4JStatusesLoader extends ParcelableStatusesLoader {
private final long mAccountId;
private final long mMaxId, mSinceId;
private final SQLiteDatabase mDatabase;
private final Handler mHandler;
private final Object[] mSavedStatusesFileArgs;
private Comparator<ParcelableStatus> mComparator;
@ -68,7 +64,6 @@ public abstract class Twitter4JStatusesLoader extends ParcelableStatusesLoader {
mMaxId = maxId;
mSinceId = sinceId;
mDatabase = TwidereApplication.getInstance(context).getSQLiteDatabase();
mHandler = new Handler();
mSavedStatusesFileArgs = savedStatusesArgs;
}
@ -117,7 +112,6 @@ public abstract class Twitter4JStatusesLoader extends ParcelableStatusesLoader {
}
final long minStatusId = statuses.isEmpty() ? -1 : Collections.min(statuses).getId();
final boolean insertGap = minStatusId > 0 && statuses.size() > 1 && !data.isEmpty() && !truncated;
mHandler.post(CacheUsersStatusesTask.getRunnable(context, new StatusListResponse(mAccountId, statuses)));
for (final Status status : statuses) {
final long id = status.getId();
final boolean deleted = deleteStatus(data, id);
@ -143,6 +137,7 @@ public abstract class Twitter4JStatusesLoader extends ParcelableStatusesLoader {
mComparator = comparator;
}
@NonNull
protected abstract List<Status> getStatuses(@NonNull Twitter twitter, Paging paging) throws TwitterException;

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -46,8 +47,9 @@ public class UserFavoritesLoader extends Twitter4JStatusesLoader {
mUserScreenName = screen_name;
}
@NonNull
@Override
public ResponseList<Status> getStatuses(final Twitter twitter, final Paging paging) throws TwitterException {
public ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
if (twitter == null) return null;
if (mUserId != -1)
return twitter.getFavorites(mUserId, paging);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -54,8 +55,9 @@ public class UserListTimelineLoader extends Twitter4JStatusesLoader {
KEY_FILTERS_FOR_RTS, true);
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(final Twitter twitter, final Paging paging) throws TwitterException {
protected ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
if (twitter == null) return null;
if (mListId > 0)
return twitter.getUserListStatuses(mListId, paging);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -51,8 +52,9 @@ public class UserTimelineLoader extends Twitter4JStatusesLoader {
mIsMyTimeline = userId > 0 ? accountId == userId : accountId == getAccountId(context, screenName);
}
@NonNull
@Override
protected ResponseList<Status> getStatuses(final Twitter twitter, final Paging paging) throws TwitterException {
protected ResponseList<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
if (twitter == null) return null;
if (mUserId != -1)
return twitter.getUserTimeline(mUserId, paging);

View File

@ -174,7 +174,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
values.getAsLong(CachedUsers.USER_ID));
mDatabaseWrapper.update(table, values, where.getSQL(), null);
newIds[result++] = mDatabaseWrapper.insertWithOnConflict(table, null,
values, SQLiteDatabase.CONFLICT_IGNORE);
values, SQLiteDatabase.CONFLICT_REPLACE);
}
} else if (tableId == TABLE_ID_SEARCH_HISTORY) {
for (final ContentValues values : valuesArray) {

View File

@ -26,115 +26,71 @@ import android.os.AsyncTask;
import com.twitter.Extractor;
import org.mariotaku.querybuilder.Expression;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedStatuses;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.TwitterWrapper.TwitterListResponse;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import twitter4j.User;
import static org.mariotaku.twidere.util.ContentValuesCreator.createCachedUser;
import static org.mariotaku.twidere.util.ContentValuesCreator.createStatus;
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkDelete;
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkInsert;
public class CacheUsersStatusesTask extends AsyncTask<Void, Void, Void> implements Constants {
public class CacheUsersStatusesTask extends AsyncTask<TwitterListResponse<twitter4j.Status>, Void, Void> implements Constants {
private final TwitterListResponse<twitter4j.Status>[] responses;
private final Context context;
@SafeVarargs
public CacheUsersStatusesTask(final Context context, final TwitterListResponse<twitter4j.Status>... responses) {
public CacheUsersStatusesTask(final Context context) {
this.context = context;
this.responses = responses;
}
@SafeVarargs
@Override
protected Void doInBackground(final Void... args) {
if (responses == null || responses.length == 0) return null;
protected final Void doInBackground(final TwitterListResponse<twitter4j.Status>... args) {
if (args == null || args.length == 0) return null;
final ContentResolver resolver = context.getContentResolver();
final Extractor extractor = new Extractor();
final Set<ContentValues> usersValues = new HashSet<>();
final Set<ContentValues> statusesValues = new HashSet<>();
final Set<ContentValues> hashTagValues = new HashSet<>();
final Set<Long> allStatusIds = new HashSet<>();
final Set<String> allHashTags = new HashSet<>();
final Set<User> users = new HashSet<>();
for (final TwitterListResponse<twitter4j.Status> response : responses) {
for (final TwitterListResponse<twitter4j.Status> response : args) {
if (response == null || response.list == null) {
continue;
}
final List<twitter4j.Status> list = response.list;
final Set<Long> userIds = new HashSet<>();
for (final twitter4j.Status status : list) {
if (status == null || status.getId() <= 0) {
continue;
for (int bulkIdx = 0, totalSize = list.size(); bulkIdx < totalSize; bulkIdx += 100) {
for (int idx = bulkIdx, end = Math.min(totalSize, bulkIdx + ContentResolverUtils.MAX_BULK_COUNT); idx < end; idx++) {
final twitter4j.Status status = list.get(idx);
if (status == null || status.getId() <= 0) {
continue;
}
final Set<ContentValues> usersValues = new HashSet<>();
final Set<ContentValues> statusesValues = new HashSet<>();
final Set<ContentValues> hashTagValues = new HashSet<>();
statusesValues.add(createStatus(status, response.accountId));
for (final String hashtag : extractor.extractHashtags(status.getText())) {
final ContentValues values = new ContentValues();
values.put(CachedHashtags.NAME, hashtag);
hashTagValues.add(values);
}
usersValues.add(createCachedUser(status.getUser()));
if (status.isRetweet()) {
usersValues.add(createCachedUser(status.getRetweetedStatus().getUser()));
}
bulkInsert(resolver, CachedStatuses.CONTENT_URI, statusesValues);
bulkInsert(resolver, CachedHashtags.CONTENT_URI, hashTagValues);
bulkInsert(resolver, CachedUsers.CONTENT_URI, usersValues);
}
if (status.isRetweet()) {
final User retweetUser = status.getRetweetedStatus().getUser();
userIds.add(retweetUser.getId());
}
allStatusIds.add(status.getId());
statusesValues.add(createStatus(status, response.account_id));
allHashTags.addAll(extractor.extractHashtags(status.getText()));
final User user = status.getUser();
users.add(user);
userIds.add(user.getId());
final ContentValues filtered_users_values = new ContentValues();
filtered_users_values.put(Filters.Users.NAME, user.getName());
filtered_users_values.put(Filters.Users.SCREEN_NAME, user.getScreenName());
final String filtered_users_where = Expression.equals(Filters.Users.USER_ID, user.getId()).getSQL();
resolver.update(Filters.Users.CONTENT_URI, filtered_users_values, filtered_users_where, null);
}
}
bulkDelete(resolver, CachedStatuses.CONTENT_URI, CachedStatuses.STATUS_ID, allStatusIds, null, false);
bulkInsert(resolver, CachedStatuses.CONTENT_URI, statusesValues);
for (final String hashtag : allHashTags) {
final ContentValues values = new ContentValues();
values.put(CachedHashtags.NAME, hashtag);
hashTagValues.add(values);
}
bulkDelete(resolver, CachedHashtags.CONTENT_URI, CachedHashtags.NAME, allHashTags, null, true);
bulkInsert(resolver, CachedHashtags.CONTENT_URI, hashTagValues);
for (final User user : users) {
usersValues.add(createCachedUser(user));
}
bulkInsert(resolver, CachedUsers.CONTENT_URI, usersValues);
return null;
}
@SafeVarargs
public static Runnable getRunnable(final Context context,
final TwitterListResponse<twitter4j.Status>... all_statuses) {
return new ExecuteCacheUserStatusesTaskRunnable(context, all_statuses);
}
static class ExecuteCacheUserStatusesTaskRunnable implements Runnable {
final Context context;
final TwitterListResponse<twitter4j.Status>[] all_statuses;
@SafeVarargs
ExecuteCacheUserStatusesTaskRunnable(final Context context,
final TwitterListResponse<twitter4j.Status>... all_statuses) {
this.context = context;
this.all_statuses = all_statuses;
}
@Override
public void run() {
AsyncTaskUtils.executeTask(new CacheUsersStatusesTask(context, all_statuses));
}
}
}

View File

@ -64,6 +64,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Mentions;
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.task.CacheUsersStatusesTask;
import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.util.collection.LongSparseMap;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
@ -1788,7 +1789,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
final List<DirectMessage> messages = new ArrayList<>();
final boolean truncated = truncateMessages(getDirectMessages(twitter, paging), messages,
since_id);
result.add(new MessageListResponse(accountId, max_id, since_id, load_item_limit, messages,
result.add(new MessageListResponse(accountId, max_id, since_id, messages,
truncated));
storeMessages(accountId, messages, isOutgoing(), true);
} catch (final TwitterException e) {
@ -1809,11 +1810,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
if (messages == null) return true;
final Uri uri = getDatabaseUri();
final ContentValues[] valuesArray = new ContentValues[messages.size()];
final long[] messageIds = new long[messages.size()];
for (int i = 0, j = messages.size(); i < j; i++) {
final DirectMessage message = messages.get(i);
messageIds[i] = message.getId();
valuesArray[i] = createDirectMessage(message, accountId, isOutgoing);
}
@ -2037,7 +2036,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
abstract class GetStatusesTask extends ManagedAsyncTask<Void, Void, List<StatusListResponse>> {
abstract class GetStatusesTask extends ManagedAsyncTask<Void, TwitterListResponse<twitter4j.Status>, List<StatusListResponse>> {
private final long[] mAccountIds, mMaxIds, mSinceIds;
@ -2055,10 +2054,10 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
return mMaxIds != null && mMaxIds.length == mAccountIds.length;
}
@SafeVarargs
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
// new CacheUsersStatusesTask(mContext, responses.toArray(array)).executeTask();
protected final void onProgressUpdate(TwitterListResponse<twitter4j.Status>... values) {
AsyncTaskUtils.executeTask(new CacheUsersStatusesTask(mContext), values);
}
private void storeStatus(long accountId, List<twitter4j.Status> statuses, long maxId, boolean truncated, boolean notify) {
@ -2159,6 +2158,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
final List<twitter4j.Status> statuses = new ArrayList<>();
final boolean truncated = truncateStatuses(getStatuses(twitter, paging), statuses, sinceId);
storeStatus(accountId, statuses, maxId, truncated, true);
publishProgress(new StatusListResponse(accountId, statuses));
} catch (final TwitterException e) {
Log.w(LOGTAG, e);
result.add(new StatusListResponse(accountId, e));

View File

@ -228,22 +228,22 @@ public class TwitterWrapper implements Constants {
public final boolean truncated;
public MessageListResponse(final long account_id, final Exception exception) {
this(account_id, -1, -1, null, false, exception);
public MessageListResponse(final long accountId, final Exception exception) {
this(accountId, -1, -1, null, false, exception);
}
public MessageListResponse(final long account_id, final List<DirectMessage> list) {
this(account_id, -1, -1, list, false, null);
public MessageListResponse(final long accountId, final List<DirectMessage> list) {
this(accountId, -1, -1, list, false, null);
}
public MessageListResponse(final long account_id, final long max_id, final long since_id,
final int load_item_limit, final List<DirectMessage> list, final boolean truncated) {
this(account_id, max_id, since_id, list, truncated, null);
public MessageListResponse(final long accountId, final long maxId, final long sinceId,
final List<DirectMessage> list, final boolean truncated) {
this(accountId, maxId, sinceId, list, truncated, null);
}
MessageListResponse(final long account_id, final long max_id, final long since_id,
MessageListResponse(final long accountId, final long maxId, final long sinceId,
final List<DirectMessage> list, final boolean truncated, final Exception exception) {
super(account_id, max_id, since_id, list, exception);
super(accountId, maxId, sinceId, list, exception);
this.truncated = truncated;
}
@ -253,22 +253,22 @@ public class TwitterWrapper implements Constants {
public final boolean truncated;
public StatusListResponse(final long account_id, final Exception exception) {
this(account_id, -1, -1, null, false, exception);
public StatusListResponse(final long accountId, final Exception exception) {
this(accountId, -1, -1, null, false, exception);
}
public StatusListResponse(final long account_id, final List<Status> list) {
this(account_id, -1, -1, list, false, null);
public StatusListResponse(final long accountId, final List<Status> list) {
this(accountId, -1, -1, list, false, null);
}
public StatusListResponse(final long account_id, final long max_id, final long since_id,
final int load_item_limit, final List<Status> list, final boolean truncated) {
this(account_id, max_id, since_id, list, truncated, null);
public StatusListResponse(final long accountId, final long maxId, final long sinceId,
final List<Status> list, final boolean truncated) {
this(accountId, maxId, sinceId, list, truncated, null);
}
StatusListResponse(final long account_id, final long max_id, final long since_id, final List<Status> list,
StatusListResponse(final long accountId, final long maxId, final long sinceId, final List<Status> list,
final boolean truncated, final Exception exception) {
super(account_id, max_id, since_id, list, exception);
super(accountId, maxId, sinceId, list, exception);
this.truncated = truncated;
}
@ -276,22 +276,22 @@ public class TwitterWrapper implements Constants {
public static class TwitterListResponse<Data> extends ListResponse<Data> {
public final long account_id, max_id, since_id;
public final long accountId, maxId, sinceId;
public TwitterListResponse(final long account_id, final Exception exception) {
this(account_id, -1, -1, null, exception);
public TwitterListResponse(final long accountId, final Exception exception) {
this(accountId, -1, -1, null, exception);
}
public TwitterListResponse(final long account_id, final long max_id, final long since_id, final List<Data> list) {
this(account_id, max_id, since_id, list, null);
public TwitterListResponse(final long accountId, final long maxId, final long sinceId, final List<Data> list) {
this(accountId, maxId, sinceId, list, null);
}
TwitterListResponse(final long account_id, final long max_id, final long since_id, final List<Data> list,
TwitterListResponse(final long accountId, final long maxId, final long sinceId, final List<Data> list,
final Exception exception) {
super(list, exception);
this.account_id = account_id;
this.max_id = max_id;
this.since_id = since_id;
this.accountId = accountId;
this.maxId = maxId;
this.sinceId = sinceId;
}
}

View File

@ -30,8 +30,10 @@ import org.mariotaku.querybuilder.Columns;
import org.mariotaku.querybuilder.Columns.Column;
import org.mariotaku.querybuilder.Expression;
import org.mariotaku.querybuilder.NewColumn;
import org.mariotaku.querybuilder.OnConflict;
import org.mariotaku.querybuilder.SQLQuery;
import org.mariotaku.querybuilder.SQLQueryBuilder;
import org.mariotaku.querybuilder.SetValue;
import org.mariotaku.querybuilder.Table;
import org.mariotaku.querybuilder.query.SQLCreateIndexQuery;
import org.mariotaku.querybuilder.query.SQLCreateTableQuery;
@ -121,12 +123,44 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
private void createTriggers(SQLiteDatabase db) {
db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_statuses").getSQL());
db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_mentions").getSQL());
db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_cached_statuses").getSQL());
db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_received_messages").getSQL());
db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_sent_messages").getSQL());
db.execSQL(SQLQueryBuilder.dropTrigger(true, "on_user_cache_update_trigger").getSQL());
db.execSQL(SQLQueryBuilder.dropTrigger(true, "delete_old_cached_hashtags").getSQL());
db.execSQL(createDeleteDuplicateStatusTrigger("delete_old_statuses", Statuses.TABLE_NAME).getSQL());
db.execSQL(createDeleteDuplicateStatusTrigger("delete_old_mentions", Mentions.TABLE_NAME).getSQL());
db.execSQL(createDeleteDuplicateStatusTrigger("delete_old_cached_statuses", CachedStatuses.TABLE_NAME).getSQL());
db.execSQL(createDeleteDuplicateMessageTrigger("delete_old_received_messages", DirectMessages.Inbox.TABLE_NAME).getSQL());
db.execSQL(createDeleteDuplicateMessageTrigger("delete_old_sent_messages", DirectMessages.Outbox.TABLE_NAME).getSQL());
// Update user info in filtered users
final Table cachedUsersTable = new Table(CachedUsers.TABLE_NAME);
final Table filteredUsersTable = new Table(Filters.Users.TABLE_NAME);
db.execSQL(SQLQueryBuilder.createTrigger(false, true, "on_user_cache_update_trigger")
.type(Type.BEFORE)
.event(Event.INSERT)
.on(cachedUsersTable)
.forEachRow(true)
.actions(SQLQueryBuilder.update(OnConflict.REPLACE, filteredUsersTable)
.set(new SetValue(new Column(Filters.Users.NAME), new Column(Table.NEW, CachedUsers.NAME)),
new SetValue(new Column(Filters.Users.SCREEN_NAME), new Column(Table.NEW, CachedUsers.SCREEN_NAME)))
.where(Expression.equals(new Column(Filters.Users.USER_ID), new Column(Table.NEW, CachedUsers.USER_ID)))
.build())
.buildSQL());
// Delete duplicated hashtags ignoring case
final Table cachedHashtagsTable = new Table(CachedHashtags.TABLE_NAME);
db.execSQL(SQLQueryBuilder.createTrigger(false, true, "delete_old_cached_hashtags")
.type(Type.BEFORE)
.event(Event.INSERT)
.on(cachedHashtagsTable)
.forEachRow(true)
.actions(SQLQueryBuilder.deleteFrom(cachedHashtagsTable)
.where(Expression.like(new Column(CachedHashtags.NAME), new Column(Table.NEW, CachedHashtags.NAME)))
.build())
.buildSQL());
}
private SQLQuery createDeleteDuplicateStatusTrigger(String triggerName, String tableName) {