improved activity gap
This commit is contained in:
parent
f153aea3ad
commit
1d42bca508
|
@ -8,7 +8,7 @@ buildscript {
|
|||
}
|
||||
dependencies {
|
||||
classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0'
|
||||
classpath 'com.android.tools.build:gradle:2.0.0-beta7'
|
||||
classpath 'com.android.tools.build:gradle:2.0.0-rc1'
|
||||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||
classpath('fr.avianey.androidsvgdrawable:gradle-plugin:3.0.0') {
|
||||
// should be excluded to avoid conflict
|
||||
|
|
|
@ -119,7 +119,7 @@ dependencies {
|
|||
compile 'com.android.support:preference-v14:23.2.1'
|
||||
compile 'com.twitter:twitter-text:1.13.0'
|
||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.4.1'
|
||||
compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.5.0'
|
||||
compile 'com.squareup:otto:1.3.8'
|
||||
compile 'dnsjava:dnsjava:2.1.7'
|
||||
compile 'com.commonsware.cwac:merge:1.1.1'
|
||||
|
@ -183,4 +183,4 @@ task svgToMipmap(type: SvgDrawableTask) {
|
|||
outputFormat = 'PNG'
|
||||
|
||||
outputType = 'mipmap'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -511,8 +511,8 @@ public abstract class AbsActivitiesFragment extends AbsContentListRecyclerViewFr
|
|||
final LinearLayoutManager layoutManager = getLayoutManager();
|
||||
adapter.setListener(this);
|
||||
registerForContextMenu(recyclerView);
|
||||
mNavigationHelper = new RecyclerViewNavigationHelper(recyclerView, layoutManager,
|
||||
adapter, this);
|
||||
mNavigationHelper = new RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter,
|
||||
this);
|
||||
mPauseOnScrollListener = new PauseRecyclerViewOnScrollListener(adapter.getMediaLoader().getImageLoader(), false, true);
|
||||
|
||||
final Bundle loaderArgs = new Bundle(getArguments());
|
||||
|
@ -521,6 +521,27 @@ public abstract class AbsActivitiesFragment extends AbsContentListRecyclerViewFr
|
|||
showProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReachingEnd() {
|
||||
final LinearLayoutManager lm = getLayoutManager();
|
||||
final ParcelableActivitiesAdapter adapter = getAdapter();
|
||||
int lastPosition = lm.findLastCompletelyVisibleItemPosition();
|
||||
final int itemCount = adapter.getItemCount();
|
||||
int finalPos = itemCount - 1;
|
||||
for (int i = lastPosition + 1; i < itemCount; i++) {
|
||||
if (adapter.getItemViewType(i) != ParcelableActivitiesAdapter.ITEM_VIEW_TYPE_EMPTY) {
|
||||
finalPos = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return finalPos >= itemCount - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReachingStart() {
|
||||
return super.isReachingStart();
|
||||
}
|
||||
|
||||
protected Object createMessageBusCallback() {
|
||||
return new StatusesBusCallback();
|
||||
}
|
||||
|
@ -578,11 +599,7 @@ public abstract class AbsActivitiesFragment extends AbsContentListRecyclerViewFr
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void setupRecyclerView(Context context, boolean compact) {
|
||||
if (compact) {
|
||||
super.setupRecyclerView(context, true);
|
||||
return;
|
||||
}
|
||||
protected void setupRecyclerView(Context context, final boolean compact) {
|
||||
final RecyclerView recyclerView = getRecyclerView();
|
||||
final ParcelableActivitiesAdapter adapter = getAdapter();
|
||||
// Dividers are drawn on bottom of view
|
||||
|
@ -595,7 +612,9 @@ public abstract class AbsActivitiesFragment extends AbsContentListRecyclerViewFr
|
|||
return false;
|
||||
}
|
||||
final int itemViewType = adapter.getItemViewType(childPos);
|
||||
// Draw only if current item and next item is TITLE_SUMMARY
|
||||
if (compact) {
|
||||
return itemViewType != ParcelableActivitiesAdapter.ITEM_VIEW_TYPE_EMPTY;
|
||||
}
|
||||
if (shouldUseDividerFor(itemViewType)) {
|
||||
if (shouldUseDividerFor(adapter.getItemViewType(childPos + 1))) {
|
||||
return true;
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.mariotaku.twidere.activity.HomeActivity;
|
|||
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter;
|
||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
|
||||
import org.mariotaku.twidere.loader.ExtendedObjectCursorLoader;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.model.ParcelableActivity;
|
||||
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
@ -55,7 +54,6 @@ import org.mariotaku.twidere.model.message.GetActivitiesTaskEvent;
|
|||
import org.mariotaku.twidere.model.message.StatusDestroyedEvent;
|
||||
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
|
||||
import org.mariotaku.twidere.model.message.StatusRetweetedEvent;
|
||||
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
|
@ -123,7 +121,7 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
|
|||
adapter.setShowAccountsColor(accountKeys.length > 1);
|
||||
final String[] projection = Activities.COLUMNS;
|
||||
return new CursorActivitiesLoader(context, uri, projection, selection, expression.whereArgs,
|
||||
sortOrder, fromUser, accountKeys);
|
||||
sortOrder, fromUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -393,19 +391,17 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
|
|||
}
|
||||
|
||||
public static class CursorActivitiesLoader extends ExtendedObjectCursorLoader<ParcelableActivity> {
|
||||
private final UserKey[] mAccountKeys;
|
||||
|
||||
public CursorActivitiesLoader(Context context, Uri uri, String[] projection,
|
||||
String selection, String[] selectionArgs, String sortOrder,
|
||||
boolean fromUser, UserKey[] accountKeys) {
|
||||
super(context, ParcelableActivityCursorIndices.class, uri, projection, selection, selectionArgs, sortOrder, fromUser);
|
||||
mAccountKeys = accountKeys;
|
||||
String selection, String[] selectionArgs,
|
||||
String sortOrder, boolean fromUser) {
|
||||
super(context, ParcelableActivityCursorIndices.class, uri, projection, selection,
|
||||
selectionArgs, sortOrder, fromUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectCursor<ParcelableActivity> createObjectCursor(Cursor cursor, ObjectCursor.CursorIndices<ParcelableActivity> indices) {
|
||||
final String[] filteredUserIds = DataStoreUtils.getFilteredUserIds(getContext());
|
||||
final ParcelableAccount[] accounts = ParcelableAccountUtils.getAccounts(getContext(), mAccountKeys);
|
||||
return new ActivityCursor(cursor, indices, filteredUserIds);
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
|
|||
if (param.shouldAbort()) return null;
|
||||
final UserKey[] accountIds = param.getAccountKeys();
|
||||
final String[] maxIds = param.getMaxIds();
|
||||
final long[] maxSortIds = param.getMaxSortIds();
|
||||
final String[] sinceIds = param.getSinceIds();
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
final int loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT);
|
||||
|
@ -88,8 +89,12 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
|
|||
final Paging paging = new Paging();
|
||||
paging.count(loadItemLimit);
|
||||
String maxId = null;
|
||||
long maxSortId = -1;
|
||||
if (maxIds != null) {
|
||||
maxId = maxIds[i];
|
||||
if (maxSortIds != null) {
|
||||
maxSortId = maxSortIds[i];
|
||||
}
|
||||
if (maxId != null) {
|
||||
paging.maxId(maxId);
|
||||
}
|
||||
|
@ -139,23 +144,44 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
|
|||
long[] deleteBound = new long[2];
|
||||
Arrays.fill(deleteBound, -1);
|
||||
List<ContentValues> valuesList = new ArrayList<>();
|
||||
for (Activity activity : activities) {
|
||||
final ParcelableActivity parcelableActivity = ParcelableActivityUtils.fromActivity(activity,
|
||||
credentials.account_key, false);
|
||||
if (deleteBound[0] < 0) {
|
||||
deleteBound[0] = parcelableActivity.min_sort_position;
|
||||
} else {
|
||||
deleteBound[0] = Math.min(deleteBound[0], parcelableActivity.min_sort_position);
|
||||
int minIdx = -1;
|
||||
long minPositionKey = -1;
|
||||
if (!activities.isEmpty()) {
|
||||
final long firstSortId = activities.get(0).getCreatedAt().getTime();
|
||||
final long lastSortId = activities.get(activities.size() - 1).getCreatedAt().getTime();
|
||||
// Get id diff of first and last item
|
||||
final long sortDiff = firstSortId - lastSortId;
|
||||
for (int i = 0, j = activities.size(); i < j; i++) {
|
||||
Activity item = activities.get(i);
|
||||
final ParcelableActivity activity = ParcelableActivityUtils.fromActivity(item,
|
||||
credentials.account_key, false);
|
||||
activity.position_key = GetStatusesTask.getPositionKey(activity.timestamp,
|
||||
activity.timestamp, lastSortId, sortDiff, i, j);
|
||||
if (deleteBound[0] < 0) {
|
||||
deleteBound[0] = activity.min_sort_position;
|
||||
} else {
|
||||
deleteBound[0] = Math.min(deleteBound[0], activity.min_sort_position);
|
||||
}
|
||||
if (deleteBound[1] < 0) {
|
||||
deleteBound[1] = activity.max_sort_position;
|
||||
} else {
|
||||
deleteBound[1] = Math.max(deleteBound[1], activity.max_sort_position);
|
||||
}
|
||||
if (minIdx == -1 || item.compareTo(activities.get(minIdx)) < 0) {
|
||||
minIdx = i;
|
||||
minPositionKey = activity.position_key;
|
||||
}
|
||||
|
||||
activity.inserted_date = System.currentTimeMillis();
|
||||
final ContentValues values = ContentValuesCreator.createActivity(activity,
|
||||
credentials, userColorNameManager);
|
||||
valuesList.add(values);
|
||||
}
|
||||
if (deleteBound[1] < 0) {
|
||||
deleteBound[1] = parcelableActivity.max_sort_position;
|
||||
} else {
|
||||
deleteBound[1] = Math.max(deleteBound[1], parcelableActivity.max_sort_position);
|
||||
}
|
||||
parcelableActivity.inserted_date = System.currentTimeMillis();
|
||||
final ContentValues values = ContentValuesCreator.createActivity(parcelableActivity,
|
||||
credentials, userColorNameManager);
|
||||
valuesList.add(values);
|
||||
}
|
||||
int olderCount = -1;
|
||||
if (minPositionKey > 0) {
|
||||
olderCount = DataStoreUtils.getActivitiesCount(context, getContentUri(), minPositionKey,
|
||||
Activities.POSITION_KEY, false, credentials.account_key);
|
||||
}
|
||||
final Uri writeUri = UriUtils.appendQueryParameters(getContentUri(), QUERY_PARAM_NOTIFY,
|
||||
notify);
|
||||
|
@ -169,7 +195,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
|
|||
String.valueOf(deleteBound[1])};
|
||||
int rowsDeleted = cr.delete(writeUri, where.getSQL(), whereArgs);
|
||||
// Why loadItemLimit / 2? because it will not acting strange in most cases
|
||||
boolean insertGap = valuesList.size() >= loadItemLimit && !noItemsBefore
|
||||
boolean insertGap = valuesList.size() >= loadItemLimit && !noItemsBefore && olderCount > 0
|
||||
&& rowsDeleted <= 0 && activities.size() > loadItemLimit / 2;
|
||||
if (insertGap && !valuesList.isEmpty()) {
|
||||
valuesList.get(valuesList.size() - 1).put(Activities.IS_GAP, true);
|
||||
|
|
|
@ -193,7 +193,7 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
|
|||
final long firstSortId = statuses.get(0).getSortId();
|
||||
final long lastSortId = statuses.get(statuses.size() - 1).getSortId();
|
||||
// Get id diff of first and last item
|
||||
long sortDiff = firstSortId - lastSortId;
|
||||
final long sortDiff = firstSortId - lastSortId;
|
||||
|
||||
for (int i = 0, j = statuses.size(); i < j; i++) {
|
||||
final Status item = statuses.get(i);
|
||||
|
|
|
@ -486,6 +486,25 @@ public class DataStoreUtils implements Constants {
|
|||
return queryCount(context, uri, selection.getSQL(), whereArgs);
|
||||
}
|
||||
|
||||
public static int getActivitiesCount(final Context context, final Uri uri, final long compare,
|
||||
String compareColumn, boolean greaterThan, UserKey... accountKeys) {
|
||||
if (context == null) return 0;
|
||||
if (accountKeys == null) {
|
||||
accountKeys = getActivatedAccountKeys(context);
|
||||
}
|
||||
final Expression selection = Expression.and(
|
||||
Expression.inArgs(new Column(Activities.ACCOUNT_KEY), accountKeys.length),
|
||||
greaterThan ? Expression.greaterThanArgs(compareColumn) : Expression.lesserThanArgs(compareColumn),
|
||||
buildActivityFilterWhereClause(getTableNameByUri(uri), null)
|
||||
);
|
||||
final String[] whereArgs = new String[accountKeys.length + 1];
|
||||
for (int i = 0; i < accountKeys.length; i++) {
|
||||
whereArgs[i] = accountKeys[i].toString();
|
||||
}
|
||||
whereArgs[accountKeys.length] = String.valueOf(compare);
|
||||
return queryCount(context, uri, selection.getSQL(), whereArgs);
|
||||
}
|
||||
|
||||
public static int getActivitiesCount(@NonNull final Context context, final Uri uri,
|
||||
final Expression extraWhere, final String[] extraWhereArgs,
|
||||
final long since, String sinceColumn, boolean followingOnly,
|
||||
|
|
|
@ -741,6 +741,7 @@ public final class Utils implements Constants {
|
|||
break;
|
||||
}
|
||||
case LINK_ID_ITEMS: {
|
||||
isAccountIdRequired = false;
|
||||
fragment = new ItemsListFragment();
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue