From 4f9175bbc2591e1e2b75246aacb0d264f5297473 Mon Sep 17 00:00:00 2001 From: Lucas Rocha Date: Mon, 24 Nov 2014 15:13:23 +0000 Subject: [PATCH] Bug 1100904 - Ensure panel updates don't happen during transitions (r=margaret) --- mobile/android/base/home/BookmarksPanel.java | 6 +- mobile/android/base/home/DynamicPanel.java | 6 +- mobile/android/base/home/HistoryPanel.java | 5 +- .../android/base/home/ReadingListPanel.java | 5 +- mobile/android/base/home/RecentTabsPanel.java | 5 +- .../RemoteTabsExpandableListFragment.java | 5 +- mobile/android/base/home/TopSitesPanel.java | 6 +- .../TransitionAwareCursorLoaderCallbacks.java | 57 +++++++++++++++++++ 8 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 mobile/android/base/home/TransitionAwareCursorLoaderCallbacks.java diff --git a/mobile/android/base/home/BookmarksPanel.java b/mobile/android/base/home/BookmarksPanel.java index 73fc480d6ad1..077114a41e68 100644 --- a/mobile/android/base/home/BookmarksPanel.java +++ b/mobile/android/base/home/BookmarksPanel.java @@ -216,7 +216,7 @@ public class BookmarksPanel extends HomeFragment { /** * Loader callbacks for the LoaderManager of this fragment. */ - private class CursorLoaderCallbacks implements LoaderCallbacks { + private class CursorLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { if (args == null) { @@ -229,7 +229,7 @@ public class BookmarksPanel extends HomeFragment { } @Override - public void onLoadFinished(Loader loader, Cursor c) { + public void onLoadFinishedAfterTransitions(Loader loader, Cursor c) { BookmarksLoader bl = (BookmarksLoader) loader; mListAdapter.swapCursor(c, bl.getFolderInfo(), bl.getRefreshType()); updateUiFromCursor(c); @@ -237,6 +237,8 @@ public class BookmarksPanel extends HomeFragment { @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); + if (mList != null) { mListAdapter.swapCursor(null); } diff --git a/mobile/android/base/home/DynamicPanel.java b/mobile/android/base/home/DynamicPanel.java index 812518c52fee..13bac2c309ba 100644 --- a/mobile/android/base/home/DynamicPanel.java +++ b/mobile/android/base/home/DynamicPanel.java @@ -352,7 +352,7 @@ public class DynamicPanel extends HomeFragment { /** * LoaderCallbacks implementation that interacts with the LoaderManager. */ - private class PanelLoaderCallbacks implements LoaderCallbacks { + private class PanelLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { final DatasetRequest request = (DatasetRequest) args.getParcelable(DATASET_REQUEST); @@ -362,7 +362,7 @@ public class DynamicPanel extends HomeFragment { } @Override - public void onLoadFinished(Loader loader, Cursor cursor) { + public void onLoadFinishedAfterTransitions(Loader loader, Cursor cursor) { final DatasetRequest request = getRequestFromLoader(loader); Log.d(LOGTAG, "Finished loader for request: " + request); @@ -373,6 +373,8 @@ public class DynamicPanel extends HomeFragment { @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); + final DatasetRequest request = getRequestFromLoader(loader); Log.d(LOGTAG, "Resetting loader for request: " + request); diff --git a/mobile/android/base/home/HistoryPanel.java b/mobile/android/base/home/HistoryPanel.java index 4d5d6d954fa9..8d1003cf9103 100644 --- a/mobile/android/base/home/HistoryPanel.java +++ b/mobile/android/base/home/HistoryPanel.java @@ -471,20 +471,21 @@ public class HistoryPanel extends HomeFragment { } } - private class CursorLoaderCallbacks implements LoaderCallbacks { + private class CursorLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { return new HistoryCursorLoader(getActivity()); } @Override - public void onLoadFinished(Loader loader, Cursor c) { + public void onLoadFinishedAfterTransitions(Loader loader, Cursor c) { mAdapter.swapCursor(c); updateUiFromCursor(c); } @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); mAdapter.swapCursor(null); } } diff --git a/mobile/android/base/home/ReadingListPanel.java b/mobile/android/base/home/ReadingListPanel.java index 5eb8666b30fc..365e6309f3f9 100644 --- a/mobile/android/base/home/ReadingListPanel.java +++ b/mobile/android/base/home/ReadingListPanel.java @@ -197,20 +197,21 @@ public class ReadingListPanel extends HomeFragment { /** * LoaderCallbacks implementation that interacts with the LoaderManager. */ - private class CursorLoaderCallbacks implements LoaderCallbacks { + private class CursorLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { return new ReadingListLoader(getActivity()); } @Override - public void onLoadFinished(Loader loader, Cursor c) { + public void onLoadFinishedAfterTransitions(Loader loader, Cursor c) { mAdapter.swapCursor(c); updateUiFromCursor(c); } @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); mAdapter.swapCursor(null); } } diff --git a/mobile/android/base/home/RecentTabsPanel.java b/mobile/android/base/home/RecentTabsPanel.java index d62013aafd65..9e55ccd2fe37 100644 --- a/mobile/android/base/home/RecentTabsPanel.java +++ b/mobile/android/base/home/RecentTabsPanel.java @@ -404,20 +404,21 @@ public class RecentTabsPanel extends HomeFragment } } - private class CursorLoaderCallbacks implements LoaderCallbacks { + private class CursorLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { return new RecentTabsCursorLoader(getActivity(), mClosedTabs); } @Override - public void onLoadFinished(Loader loader, Cursor c) { + public void onLoadFinishedAfterTransitions(Loader loader, Cursor c) { mAdapter.swapCursor(c); updateUiFromCursor(c); } @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); mAdapter.swapCursor(null); } } diff --git a/mobile/android/base/home/RemoteTabsExpandableListFragment.java b/mobile/android/base/home/RemoteTabsExpandableListFragment.java index 1f263b6408e4..8a093e3fd4fd 100644 --- a/mobile/android/base/home/RemoteTabsExpandableListFragment.java +++ b/mobile/android/base/home/RemoteTabsExpandableListFragment.java @@ -392,14 +392,14 @@ public class RemoteTabsExpandableListFragment extends HomeFragment implements Re } } - private class CursorLoaderCallbacks implements LoaderCallbacks { + private class CursorLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { return new RemoteTabsCursorLoader(getActivity()); } @Override - public void onLoadFinished(Loader loader, Cursor c) { + public void onLoadFinishedAfterTransitions(Loader loader, Cursor c) { final List clients = TabsAccessor.getClientsFromCursor(c); // Filter the hidden clients out of the clients list. The clients @@ -421,6 +421,7 @@ public class RemoteTabsExpandableListFragment extends HomeFragment implements Re @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); mAdapter.replaceClients(null); } } diff --git a/mobile/android/base/home/TopSitesPanel.java b/mobile/android/base/home/TopSitesPanel.java index c0f0cf1c7d8d..8c95d4626c01 100644 --- a/mobile/android/base/home/TopSitesPanel.java +++ b/mobile/android/base/home/TopSitesPanel.java @@ -689,7 +689,7 @@ public class TopSitesPanel extends HomeFragment { } } - private class CursorLoaderCallbacks implements LoaderCallbacks { + private class CursorLoaderCallbacks extends TransitionAwareCursorLoaderCallbacks { @Override public Loader onCreateLoader(int id, Bundle args) { trace("Creating TopSitesLoader: " + id); @@ -707,7 +707,7 @@ public class TopSitesPanel extends HomeFragment { * Why that is... dunno. */ @Override - public void onLoadFinished(Loader loader, Cursor c) { + protected void onLoadFinishedAfterTransitions(Loader loader, Cursor c) { debug("onLoadFinished: " + c.getCount() + " rows."); mListAdapter.swapCursor(c); @@ -752,6 +752,8 @@ public class TopSitesPanel extends HomeFragment { @Override public void onLoaderReset(Loader loader) { + super.onLoaderReset(loader); + if (mListAdapter != null) { mListAdapter.swapCursor(null); } diff --git a/mobile/android/base/home/TransitionAwareCursorLoaderCallbacks.java b/mobile/android/base/home/TransitionAwareCursorLoaderCallbacks.java new file mode 100644 index 000000000000..c9753b50da51 --- /dev/null +++ b/mobile/android/base/home/TransitionAwareCursorLoaderCallbacks.java @@ -0,0 +1,57 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.home; + +import android.database.Cursor; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; + +import org.mozilla.gecko.animation.TransitionsTracker; + +/** + * A {@link LoaderCallbacks} implementation that avoids running its + * {@link #onLoadFinished(Loader, Cursor)} method during animations as it's + * likely to trigger a layout traversal as a result of a cursor swap in the + * target adapter. + */ +public abstract class TransitionAwareCursorLoaderCallbacks implements LoaderCallbacks { + private OnLoadFinishedRunnable onLoadFinishedRunnable; + + @Override + public void onLoadFinished(Loader loader, Cursor c) { + if (onLoadFinishedRunnable != null) { + TransitionsTracker.cancelPendingAction(onLoadFinishedRunnable); + } + + onLoadFinishedRunnable = new OnLoadFinishedRunnable(loader, c); + TransitionsTracker.runAfterTransitions(onLoadFinishedRunnable); + } + + protected abstract void onLoadFinishedAfterTransitions(Loader loade, Cursor c); + + @Override + public void onLoaderReset(Loader loader) { + if (onLoadFinishedRunnable != null) { + TransitionsTracker.cancelPendingAction(onLoadFinishedRunnable); + onLoadFinishedRunnable = null; + } + } + + private class OnLoadFinishedRunnable implements Runnable { + private final Loader loader; + private final Cursor cursor; + + public OnLoadFinishedRunnable(Loader loader, Cursor cursor) { + this.loader = loader; + this.cursor = cursor; + } + + @Override + public void run() { + onLoadFinishedAfterTransitions(loader, cursor); + onLoadFinishedRunnable = null; + } + } +} \ No newline at end of file