From 2a9fefd54e933d35ddb433a1282d1e841a33f8fc Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Fri, 26 May 2017 16:45:53 +1000 Subject: [PATCH] Simplify logic in UpdatesAdapter. No longer do we try to nicely maintain the state of the adapter in "Updates" in order to notify the recycler view about changes to its underlying data. Instead, we just rebuild the entire structure each time a new thing needs to be shown/removed. This means no more smooth scrolling to the relevant item after it is changed, but it results in a far less buggy interface. --- .../fdroid/views/updates/UpdatesAdapter.java | 119 +++++------------- 1 file changed, 32 insertions(+), 87 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java index 441964611..59c7507e5 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/updates/UpdatesAdapter.java @@ -6,15 +6,12 @@ import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.os.Bundle; -import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; import android.view.ViewGroup; import com.hannesdorfmann.adapterdelegates3.AdapterDelegatesManager; @@ -33,7 +30,9 @@ import org.fdroid.fdroid.views.updates.items.UpdateableAppsHeader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Manages the following types of information: @@ -68,9 +67,6 @@ public class UpdatesAdapter extends RecyclerView.Adapter appsToShowStatus = new ArrayList<>(); private final List appsToPromptForDonation = new ArrayList<>(); private final List appsToNotifyAbout = new ArrayList<>(); @@ -135,17 +131,6 @@ public class UpdatesAdapter extends RecyclerView.Adapter toShowStatusPackageNames = new HashSet<>(appsToShowStatus.size()); + for (AppStatus app : appsToShowStatus) { + toShowStatusPackageNames.add(app.status.app.packageName); + items.add(app); + } - if (updateableApps != null && updateableApps.size() > 0) { - items.add(new UpdateableAppsHeader(activity, this, updateableApps)); - if (showAllUpdateableApps) { - items.addAll(updateableApps); + if (updateableApps != null) { + // Only count/show apps which are not shown above in the "Apps to show status" list. + List updateableAppsToShow = new ArrayList<>(updateableApps.size()); + for (UpdateableApp app : updateableApps) { + if (!toShowStatusPackageNames.contains(app.app.packageName)) { + updateableAppsToShow.add(app); + } + } + + if (updateableAppsToShow.size() > 0) { + items.add(new UpdateableAppsHeader(activity, this, updateableAppsToShow)); + + if (showAllUpdateableApps) { + items.addAll(updateableAppsToShow); + } } } @@ -189,12 +189,6 @@ public class UpdatesAdapter extends RecyclerView.Adapter onCreateLoader(int id, Bundle args) { return new CursorLoader( @@ -224,12 +218,7 @@ public class UpdatesAdapter extends RecyclerView.Adapter loader, Cursor cursor) { - int numberRemoved = updateableApps.size(); - boolean hadHeader = updateableApps.size() > 0; - boolean willHaveHeader = cursor.getCount() > 0; - updateableApps.clear(); - notifyItemRangeRemoved(appsToShowStatus.size(), numberRemoved + (hadHeader ? 1 : 0)); cursor.moveToFirst(); while (!cursor.isAfterLast()) { @@ -238,7 +227,7 @@ public class UpdatesAdapter extends RecyclerView.Adapter 0) { - int size = appsToShowStatus.size(); - appsToShowStatus.clear(); - notifyItemRangeRemoved(0, size); - } - populateAppStatuses(); - notifyItemRangeInserted(0, appsToShowStatus.size()); - - if (recyclerView != null) { - recyclerView.smoothScrollToPosition(0); - } + notifyDataSetChanged(); } - private void onAppStatusAdded(String apkUrl) { - // We could try and find the specific place where we need to add our new item, but it is - // far simpler to clear the list and rebuild it (sorting it in the process). + private void onAppStatusAdded() { appsToShowStatus.clear(); populateAppStatuses(); - - // After adding the new item to our list (somewhere) we can then look it back up again in - // order to notify the recycler view and scroll to that item. - int positionOfNewApp = -1; - for (int i = 0; i < appsToShowStatus.size(); i++) { - if (TextUtils.equals(appsToShowStatus.get(i).status.getUniqueKey(), apkUrl)) { - positionOfNewApp = i; - break; - } - } - - if (positionOfNewApp != -1) { - notifyItemInserted(positionOfNewApp); - - if (recyclerView != null) { - recyclerView.smoothScrollToPosition(positionOfNewApp); - } - } + notifyDataSetChanged(); } - private void onAppStatusRemoved(String apkUrl) { - // Find out where the item is in our internal data structure, so that we can remove it and - // also notify the recycler view appropriately. - int positionOfOldApp = -1; - for (int i = 0; i < appsToShowStatus.size(); i++) { - if (TextUtils.equals(appsToShowStatus.get(i).status.getUniqueKey(), apkUrl)) { - positionOfOldApp = i; - break; - } - } - - if (positionOfOldApp != -1) { - appsToShowStatus.remove(positionOfOldApp); - - populateItems(); - notifyItemRemoved(positionOfOldApp); - } + private void onAppStatusRemoved() { + appsToShowStatus.clear(); + populateAppStatuses(); + notifyDataSetChanged(); } private final BroadcastReceiver receiverAppStatusChanges = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - String apkUrl = intent.getStringExtra(AppUpdateStatusManager.EXTRA_APK_URL); - switch (intent.getAction()) { case AppUpdateStatusManager.BROADCAST_APPSTATUS_LIST_CHANGED: onManyAppStatusesChanged(intent.getStringExtra(AppUpdateStatusManager.EXTRA_REASON_FOR_CHANGE)); break; case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED: - onAppStatusAdded(apkUrl); + onAppStatusAdded(); break; case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED: - onAppStatusRemoved(apkUrl); + onAppStatusRemoved(); break; } }