Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java

Issue 2360813004: 📰 Stop refreshing the whole NTP for every adapter change (Closed)
Patch Set: rebase again -_- Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index 99dd3baa71222bc6da6e0728de6b2a8038a6b7a0..f512c57635992162082f5ecaa59683bd3f3202fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -42,7 +42,7 @@
* elements will be the cards shown to the user
*/
public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
- implements SuggestionsSource.Observer {
+ implements SuggestionsSource.Observer, ItemGroup.Observer {
private static final String TAG = "Ntp";
private final NewTabPageManager mNewTabPageManager;
@@ -127,19 +127,38 @@ public void onChildDraw(Canvas c, RecyclerView recyclerView, ViewHolder viewHold
}
/**
- * Constructor to create the manager for all the cards to display on the NTP
+ * Creates the adapter that will manage all the cards to display on the NTP.
*
* @param manager the NewTabPageManager to use to interact with the rest of the system.
* @param aboveTheFoldView the layout encapsulating all the above-the-fold elements
* (logo, search box, most visited tiles)
- * @param suggestionsSource the bridge to interact with the content suggestions service.
* @param uiConfig the NTP UI configuration, to be passed to created views.
*/
- public NewTabPageAdapter(NewTabPageManager manager, View aboveTheFoldView, UiConfig uiConfig) {
+ public static NewTabPageAdapter create(
+ NewTabPageManager manager, View aboveTheFoldView, UiConfig uiConfig) {
+ NewTabPageAdapter adapter = new NewTabPageAdapter(manager, aboveTheFoldView, uiConfig);
+ adapter.initializeSections();
+ return adapter;
+ }
+
+ /**
+ * Constructor for {@link NewTabPageAdapter}. The object is not completely ready to be used
+ * until {@link #initializeSections()} is called. Usage reserved for testing, prefer calling
+ * {@link NewTabPageAdapter#create(NewTabPageManager, View, UiConfig)} in production code.
+ */
+ @VisibleForTesting
+ NewTabPageAdapter(NewTabPageManager manager, View aboveTheFoldView, UiConfig uiConfig) {
mNewTabPageManager = manager;
mAboveTheFoldView = aboveTheFoldView;
mUiConfig = uiConfig;
+ }
+ /**
+ * Initialises the sections to be handled by this adapter. Events about categories for which
+ * a section has not been registered at this point will be ignored.
+ */
+ @VisibleForTesting
+ void initializeSections() {
SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsSource();
int[] categories = suggestionsSource.getCategories();
@@ -203,7 +222,6 @@ public void onNewSuggestions(@CategoryInt int category) {
if (suggestions.isEmpty()) return;
setSuggestions(category, suggestions, status);
- updateGroups();
NewTabPageUma.recordSnippetAction(NewTabPageUma.SNIPPETS_ACTION_SHOWN);
}
@@ -222,18 +240,16 @@ public void onCategoryStatusChanged(@CategoryInt int category, @CategoryStatusEn
if (status == CategoryStatus.CATEGORY_EXPLICITLY_DISABLED
|| status == CategoryStatus.LOADING_ERROR) {
// Need to remove the entire section from the UI immediately.
- mSections.remove(category);
+ removeSection(mSections.get(category));
} else {
mSections.get(category).setStatus(status);
}
- updateGroups();
}
@Override
public void onSuggestionInvalidated(@CategoryInt int category, String idWithinCategory) {
if (!mSections.containsKey(category)) return;
mSections.get(category).removeSuggestionById(idWithinCategory);
- updateGroups();
}
@Override
@@ -358,10 +374,58 @@ private void updateGroups() {
mGroups.add(mBottomSpacer);
}
- // TODO(bauerb): Notify about a smaller range: https://crbug.com/627512
notifyDataSetChanged();
}
+ private void removeSection(SuggestionsSection section) {
+ mSections.remove(section.getCategory());
+ int startPos = getGroupPositionOffset(section);
+ mGroups.remove(section);
+ int removedItems = section.getItems().size();
+
+ if (mSections.isEmpty()) {
+ if (mGroups.remove(mFooter)) ++removedItems;
+ if (mGroups.remove(mBottomSpacer)) ++removedItems;
+ }
+
+ notifyItemRangeRemoved(startPos, removedItems);
+ notifyItemChanged(getItems().size() - 1); // Refresh the spacer too.
+ }
+
+ @Override
+ public void notifyGroupChanged(ItemGroup group, int itemCountBefore, int itemCountAfter) {
+ int startPos = getGroupPositionOffset(group);
+
+ if (group instanceof SuggestionsSection) {
+ // The header is stable in sections. Don't notify about it.
+ ++startPos;
+ --itemCountBefore;
+ --itemCountAfter;
+ }
+
+ if (itemCountBefore < itemCountAfter) {
+ notifyItemRangeChanged(startPos, itemCountBefore);
+ notifyItemRangeInserted(startPos + itemCountBefore, itemCountAfter - itemCountBefore);
+ } else {
+ notifyItemRangeChanged(startPos, itemCountAfter);
+ notifyItemRangeRemoved(startPos + itemCountAfter, itemCountBefore - itemCountAfter);
+ }
+
+ notifyItemChanged(getItems().size() - 1); // Refresh the spacer too.
+ }
+
+ @Override
+ public void notifyItemInserted(ItemGroup group, int itemPosition) {
+ notifyItemInserted(getGroupPositionOffset(group) + itemPosition);
+ notifyItemChanged(getItems().size() - 1); // Refresh the spacer too.
+ }
+
+ @Override
+ public void notifyItemRemoved(ItemGroup group, int itemPosition) {
+ notifyItemRemoved(getGroupPositionOffset(group) + itemPosition);
+ notifyItemChanged(getItems().size() - 1); // Refresh the spacer too.
+ }
+
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
@@ -392,9 +456,7 @@ public void dismissItem(int position) {
private void dismissSection(SuggestionsSection section) {
mNewTabPageManager.getSuggestionsSource().dismissCategory(section.getCategory());
-
- mSections.remove(section.getCategory());
- updateGroups();
+ removeSection(section);
}
private void dismissSuggestion(int position) {
@@ -418,22 +480,11 @@ public void onResult(Boolean result) {
}
});
- mRecyclerView.announceForAccessibility(mRecyclerView.getResources().getString(
- R.string.ntp_accessibility_item_removed, suggestion.mTitle));
+ announceItemRemoved(suggestion.mTitle);
suggestionsSource.dismissSuggestion(suggestion);
SuggestionsSection section = (SuggestionsSection) getGroup(position);
section.removeSuggestion(suggestion);
-
- if (section.hasSuggestions()) {
- // If one of many suggestions was dismissed, it's a simple item removal, which can be
- // animated smoothly by the RecyclerView.
- notifyItemRemoved(position);
- } else {
- // If the last suggestion was dismissed, multiple items will have changed, so mark
- // everything as changed.
- notifyDataSetChanged();
- }
}
/**
@@ -477,4 +528,10 @@ int getGroupPositionOffset(ItemGroup group) {
SnippetArticle getSuggestionAt(int position) {
return (SnippetArticle) getItems().get(position);
}
+
+ @VisibleForTesting
+ void announceItemRemoved(String suggestionTitle) {
+ mRecyclerView.announceForAccessibility(mRecyclerView.getResources().getString(
+ R.string.ntp_accessibility_item_removed, suggestionTitle));
+ }
}

Powered by Google App Engine
This is Rietveld 408576698