Bug 1116599 - Use a cache to create a GeckoMenu.findItem fast path r=rnewman
authorMark Finkle <mfinkle@mozilla.com>
Wed, 31 Dec 2014 14:32:44 -0500
changeset 221772 0d284cdc38f6a7031d811a12638f6d8f619e730a
parent 221771 d3c44062ebbb2606978acdf898b407dfbe9146ff
child 221773 e517f97929b49683fcc3804a9b9820597f33a075
push id28041
push userkwierso@gmail.com
push dateThu, 01 Jan 2015 00:53:12 +0000
treeherdermozilla-central@3c296aa11c51 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman
bugs1116599
milestone37.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 1116599 - Use a cache to create a GeckoMenu.findItem fast path r=rnewman
mobile/android/base/menu/GeckoMenu.java
--- a/mobile/android/base/menu/GeckoMenu.java
+++ b/mobile/android/base/menu/GeckoMenu.java
@@ -10,16 +10,17 @@ import org.mozilla.gecko.util.ThreadUtil
 import org.mozilla.gecko.util.ThreadUtils.AssertBehavior;
 import org.mozilla.gecko.widget.GeckoActionProvider;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.SparseArray;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.SubMenu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
@@ -85,16 +86,19 @@ public class GeckoMenu extends ListView
         public void removeActionItem(View actionItem);
     }
 
     protected static final int NO_ID = 0;
 
     // List of all menu items.
     private final List<GeckoMenuItem> mItems;
 
+    // Quick lookup array used to make a fast path in findItem.
+    private final SparseArray<MenuItem> mItemsById;
+
     // Map of "always" action-items in action-bar and their views.
     private final Map<GeckoMenuItem, View> mPrimaryActionItems;
 
     // Map of "ifRoom" action-items in action-bar and their views.
     private final Map<GeckoMenuItem, View> mSecondaryActionItems;
 
     // Reference to a callback for menu events.
     private Callback mCallback;
@@ -129,16 +133,17 @@ public class GeckoMenu extends ListView
                                          LayoutParams.MATCH_PARENT));
 
         // Attach an adapter.
         mAdapter = new MenuItemsAdapter();
         setAdapter(mAdapter);
         setOnItemClickListener(this);
 
         mItems = new ArrayList<GeckoMenuItem>();
+        mItemsById = new SparseArray<MenuItem>();
         mPrimaryActionItems = new HashMap<GeckoMenuItem, View>();
         mSecondaryActionItems = new HashMap<GeckoMenuItem, View>();
 
         mPrimaryActionItemBar = (DefaultActionItemBar) LayoutInflater.from(context).inflate(R.layout.menu_action_bar, null);
         mSecondaryActionItemBar = (DefaultActionItemBar) LayoutInflater.from(context).inflate(R.layout.menu_secondary_action_bar, null);
     }
 
     private static void assertOnUiThread() {
@@ -357,25 +362,34 @@ public class GeckoMenu extends ListView
 
     private void showMenu(View viewForMenu) {
         if (mMenuPresenter != null)
             mMenuPresenter.showMenu(viewForMenu);
     }
 
     @Override
     public MenuItem findItem(int id) {
+        assertOnUiThread();
+        MenuItem quickItem = mItemsById.get(id);
+        if (quickItem != null) {
+            return quickItem;
+        }
+
         for (GeckoMenuItem menuItem : mItems) {
             if (menuItem.getItemId() == id) {
+                mItemsById.put(id, menuItem);
                 return menuItem;
             } else if (menuItem.hasSubMenu()) {
                 if (!menuItem.hasActionProvider()) {
                     SubMenu subMenu = menuItem.getSubMenu();
                     MenuItem item = subMenu.findItem(id);
-                    if (item != null)
+                    if (item != null) {
+                        mItemsById.put(id, item);
                         return item;
+                    }
                 }
             }
         }
         return null;
     }
 
     @Override
     public MenuItem getItem(int index) {
@@ -419,16 +433,19 @@ public class GeckoMenu extends ListView
 
     @Override
     public void removeItem(int id) {
         assertOnUiThread();
         GeckoMenuItem item = (GeckoMenuItem) findItem(id);
         if (item == null)
             return;
 
+        // Remove it from the cache.
+        mItemsById.remove(id);
+
         // Remove it from any sub-menu.
         for (GeckoMenuItem menuItem : mItems) {
             if (menuItem.hasSubMenu()) {
                 SubMenu subMenu = menuItem.getSubMenu();
                 if (subMenu != null && subMenu.findItem(id) != null) {
                     subMenu.removeItem(id);
                     return;
                 }
@@ -806,16 +823,17 @@ public class GeckoMenu extends ListView
 
         public void removeMenuItem(GeckoMenuItem menuItem) {
             // Remove it from the list.
             mItems.remove(menuItem);
             notifyDataSetChanged();
         }
 
         public void clear() {
+            mItemsById.clear();
             mItems.clear();
             notifyDataSetChanged();
         }
 
         public GeckoMenuItem getMenuItem(int id) {
             for (GeckoMenuItem item : mItems) {
                 if (item.getItemId() == id)
                     return item;