Bug 1220928 - Handle configuration changes. r=sebastian
authorChenxia Liu <liuche@mozilla.com>
Mon, 28 Mar 2016 17:02:16 -0700
changeset 291304 251bd4b73f611357597860acc356d665d5ffcf95
parent 291303 c63615d8c252e55111fbb35daec7f0f35a53b73d
child 291305 af73f5dcd1b1d8f13fbf718b223a0e546b8498ff
push id74545
push userkwierso@gmail.com
push dateFri, 01 Apr 2016 23:05:42 +0000
treeherdermozilla-inbound@c410d4e20586 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssebastian
bugs1220928
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1220928 - Handle configuration changes. r=sebastian MozReview-Commit-ID: E5MoWlcMCdj
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
@@ -42,45 +42,45 @@ public class CombinedHistoryAdapter exte
 
         public static int itemTypeToViewType(ItemType itemType) {
             return itemType.ordinal();
         }
     }
 
     private List<RemoteClient> remoteClients = Collections.emptyList();
     private List<RemoteTab> clientChildren;
+    private int remoteClientIndexOfParent = -1;
     private Cursor historyCursor;
 
     // Maintain group collapsed and hidden state. Only accessed from the UI thread.
     protected static RemoteTabsExpandableListState sState;
 
     // List of hidden remote clients.
     // Only accessed from the UI thread.
     protected final List<RemoteClient> hiddenClients = new ArrayList<>();
 
     // We use a sparse array to store each section header's position in the panel [more cheaply than a HashMap].
     private final SparseArray<CombinedHistoryPanel.SectionHeader> sectionHeaders;
 
     private final Context context;
 
-    private boolean inChildView = false;
-
-    public CombinedHistoryAdapter(Context context) {
+    public CombinedHistoryAdapter(Context context, int savedParentIndex) {
         super();
         this.context = context;
         sectionHeaders = new SparseArray<>();
 
         // This races when multiple Fragments are created. That's okay: one
         // will win, and thereafter, all will be okay. If we create and then
         // drop an instance the shared SharedPreferences backing all the
         // instances will maintain the state for us. Since everything happens on
         // the UI thread, this doesn't even need to be volatile.
         if (sState == null) {
             sState = new RemoteTabsExpandableListState(GeckoSharedPrefs.forProfile(context));
         }
+        remoteClientIndexOfParent = savedParentIndex;
     }
 
     public void setClients(List<RemoteClient> clients) {
         hiddenClients.clear();
         remoteClients.clear();
 
         final Iterator<RemoteClient> it = clients.iterator();
         while (it.hasNext()) {
@@ -181,32 +181,40 @@ public class CombinedHistoryAdapter exte
             for (int i = 1; i < clientChildren.size(); i++) {
                 urls.put(clientChildren.get(i).url);
             }
             return urls;
         }
         return null;
     }
 
+    public int getParentIndex() {
+        return remoteClientIndexOfParent;
+    }
+
+    private boolean isInChildView() {
+        return remoteClientIndexOfParent != -1;
+    }
+
     public void showChildView(int parentPosition) {
         if (clientChildren == null) {
             clientChildren = new ArrayList<>();
         }
         // Handle "back" view.
         clientChildren.add(null);
-        clientChildren.addAll(remoteClients.get(transformAdapterPositionForDataStructure(ItemType.CLIENT, parentPosition)).tabs);
-        inChildView = true;
+        remoteClientIndexOfParent = transformAdapterPositionForDataStructure(ItemType.CLIENT, parentPosition);
+        clientChildren.addAll(remoteClients.get(remoteClientIndexOfParent).tabs);
         notifyDataSetChanged();
     }
 
     public boolean exitChildView() {
-        if (!inChildView) {
+        if (!isInChildView()) {
             return false;
         }
-        inChildView = false;
+        remoteClientIndexOfParent = -1;
         clientChildren.clear();
         notifyDataSetChanged();
         return true;
     }
 
     private ItemType getItemTypeForPosition(int position) {
         return ItemType.viewTypeToItemType(getItemViewType(position));
     }
@@ -282,17 +290,17 @@ public class CombinedHistoryAdapter exte
                 return new CombinedHistoryItem.HistoryItem(view);
             default:
                 throw new IllegalArgumentException("Unexpected Home Panel item type");
         }
     }
 
     @Override
     public int getItemViewType(int position) {
-        if (inChildView) {
+        if (isInChildView()) {
             if (position == 0) {
                 return ItemType.itemTypeToViewType(ItemType.NAVIGATION_BACK);
             }
             return ItemType.itemTypeToViewType(ItemType.CHILD);
         } else {
             final int numClients = remoteClients.size();
             if (position < numClients) {
                 if (!hiddenClients.isEmpty() && position == numClients - 1) {
@@ -307,18 +315,23 @@ public class CombinedHistoryAdapter exte
             }
 
             return ItemType.itemTypeToViewType(ItemType.HISTORY);
         }
     }
 
     @Override
     public int getItemCount() {
-        if (inChildView) {
-            return (clientChildren == null) ? 0 : clientChildren.size();
+        if (isInChildView()) {
+            if (clientChildren == null) {
+                clientChildren = new ArrayList<>();
+                clientChildren.add(null);
+                clientChildren.addAll(remoteClients.get(remoteClientIndexOfParent).tabs);
+            }
+            return clientChildren.size();
         } else {
             final int historySize = historyCursor == null ? 0 : historyCursor.getCount();
             return remoteClients.size() + historySize + sectionHeaders.size();
         }
     }
 
     /**
      * Add only the SectionHeaders that have history items within their range to a SparseArray, where the
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
 import android.app.AlertDialog;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.res.Configuration;
 import android.database.Cursor;
 import android.os.Bundle;
 import android.support.v4.app.LoaderManager;
 import android.support.v4.content.Loader;
 import android.support.v7.widget.DefaultItemAnimator;
 import android.text.SpannableStringBuilder;
 import android.text.TextPaint;
 import android.text.method.LinkMovementMethod;
@@ -77,16 +78,17 @@ public class CombinedHistoryPanel extend
 
     // String placeholders to mark formatting.
     private final static String FORMAT_S1 = "%1$s";
     private final static String FORMAT_S2 = "%2$s";
 
     private CombinedHistoryRecyclerView mRecyclerView;
     private CombinedHistoryAdapter mAdapter;
     private CursorLoaderCallbacks mCursorLoaderCallbacks;
+    private int mSavedParentIndex = -1;
 
     private OnPanelLevelChangeListener.PanelLevel mPanelLevel = OnPanelLevelChangeListener.PanelLevel.PARENT;
     private Button mPanelFooterButton;
     // Reference to the View to display when there are no results.
     private View mEmptyView;
 
     public interface OnPanelLevelChangeListener {
         enum PanelLevel {
@@ -101,17 +103,17 @@ public class CombinedHistoryPanel extend
         return inflater.inflate(R.layout.home_combined_history_panel, container, false);
     }
 
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
         mRecyclerView = (CombinedHistoryRecyclerView) view.findViewById(R.id.combined_recycler_view);
-        mAdapter = new CombinedHistoryAdapter(getContext());
+        mAdapter = new CombinedHistoryAdapter(getContext(), mSavedParentIndex);
         mRecyclerView.setAdapter(mAdapter);
         mRecyclerView.setItemAnimator(new DefaultItemAnimator());
         mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext()));
         mRecyclerView.setOnHistoryClickedListener(mUrlOpenListener);
         mRecyclerView.setOnPanelLevelChangeListener(new OnLevelChangeListener());
         mRecyclerView.setHiddenClientsDialogBuilder(new HiddenClientsHelper());
         registerForContextMenu(mRecyclerView);
 
@@ -121,16 +123,27 @@ public class CombinedHistoryPanel extend
 
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         mCursorLoaderCallbacks = new CursorLoaderCallbacks();
     }
 
     @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        if (isVisible()) {
+            // The parent stack is saved just so that the folder state can be
+            // restored on rotation.
+            mSavedParentIndex = mAdapter.getParentIndex();
+        }
+    }
+
+    @Override
     protected void load() {
         getLoaderManager().initLoader(LOADER_ID_HISTORY, null, mCursorLoaderCallbacks);
         getLoaderManager().initLoader(LOADER_ID_REMOTE, null, mCursorLoaderCallbacks);
     }
 
     private static class RemoteTabsCursorLoader extends SimpleCursorLoader {
         private final GeckoProfile mProfile;
 
@@ -281,17 +294,17 @@ public class CombinedHistoryPanel extend
                             Telemetry.sendUIEvent(TelemetryContract.Event.SANITIZE, TelemetryContract.Method.BUTTON, "history");
                         }
                     });
 
                     dialogBuilder.show();
                     break;
 
                 case CHILD:
-                    final JSONArray tabUrls = ((CombinedHistoryAdapter) mRecyclerView.getAdapter()).getCurrentChildTabs();
+                    final JSONArray tabUrls = mAdapter.getCurrentChildTabs();
                     if (tabUrls != null) {
                         final JSONObject message = new JSONObject();
                         try {
                             message.put("urls", tabUrls);
                             message.put("shouldNotifyTabsOpenedToJava", false);
                             GeckoAppShell.notifyObservers("Tabs:OpenMultiple", message.toString());
                         } catch (JSONException e) {
                             Log.e(LOGTAG, "Error making JSON message to open tabs");
@@ -421,17 +434,17 @@ public class CombinedHistoryPanel extend
         if (!(menuInfo instanceof RemoteTabsClientContextMenuInfo)) {
             return false;
         }
 
         final RemoteTabsClientContextMenuInfo info = (RemoteTabsClientContextMenuInfo) menuInfo;
 
         final int itemId = item.getItemId();
         if (itemId == R.id.home_remote_tabs_hide_client) {
-            ((CombinedHistoryAdapter) mRecyclerView.getAdapter()).removeItem(info.position);
+            mAdapter.removeItem(info.position);
             return true;
         }
 
         return false;
     }
 
     interface DialogBuilder<E> {
         void createAndShowDialog(List<E> items);
@@ -448,17 +461,17 @@ public class CombinedHistoryPanel extend
             dialog.show(getActivity().getSupportFragmentManager(), "show-clients");
         }
 
 
     }
 
     @Override
     public void onClients(List<RemoteClient> clients) {
-        ((CombinedHistoryAdapter) mRecyclerView.getAdapter()).unhideClients(clients);
+        mAdapter.unhideClients(clients);
     }
 
     /**
      * Stores information regarding the creation of the context menu for a remote client.
      */
     protected static class RemoteTabsClientContextMenuInfo extends HomeContextMenuInfo {
         protected final RemoteClient client;