From 2a7416ffa7e6ee829bc84499e36d13744e24db77 Mon Sep 17 00:00:00 2001 From: serso Date: Mon, 8 Sep 2014 20:06:59 +0200 Subject: [PATCH] views cache for fast lookup --- .../calculator/AbstractCalculatorHelper.java | 98 ++++++++++--------- .../android/calculator/view/ViewsCache.java | 95 ++++++++++++++++++ 2 files changed, 147 insertions(+), 46 deletions(-) create mode 100644 android-app/src/main/java/org/solovyev/android/calculator/view/ViewsCache.java diff --git a/android-app/src/main/java/org/solovyev/android/calculator/AbstractCalculatorHelper.java b/android-app/src/main/java/org/solovyev/android/calculator/AbstractCalculatorHelper.java index 62816442..91202a66 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/AbstractCalculatorHelper.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/AbstractCalculatorHelper.java @@ -38,6 +38,7 @@ import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.view.AngleUnitsButton; import org.solovyev.android.calculator.view.NumeralBasesButton; import org.solovyev.android.calculator.view.OnDragListenerVibrator; +import org.solovyev.android.calculator.view.ViewsCache; import org.solovyev.android.history.HistoryDragProcessor; import org.solovyev.android.view.drag.*; import org.solovyev.common.listeners.JListeners; @@ -63,6 +64,9 @@ import static org.solovyev.android.calculator.model.AndroidCalculatorEngine.Pref */ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSharedPreferenceChangeListener { + @Nonnull + private static final List viewIds = new ArrayList(200); + @Nonnull private CalculatorPreferences.Gui.Layout layout; @@ -121,15 +125,16 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, activity); - setOnDragListeners(root, dragPreferences, preferences); + final ViewsCache views = ViewsCache.forView(root); + setOnDragListeners(views, dragPreferences, preferences); final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor(getCalculator()), dragPreferences), vibrator, preferences); - final DragButton historyButton = getButton(root, R.id.cpp_button_history); + final DragButton historyButton = getButton(views, R.id.cpp_button_history); if (historyButton != null) { historyButton.setOnDragListener(historyOnDragListener); } - final DragButton subtractionButton = getButton(root, R.id.cpp_button_subtraction); + final DragButton subtractionButton = getButton(views, R.id.cpp_button_subtraction); if (subtractionButton != null) { subtractionButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new SimpleOnDragListener.DragProcessor() { @Override @@ -145,64 +150,64 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(), dragPreferences), vibrator, preferences); - final DragButton rightButton = getButton(root, R.id.cpp_button_right); + final DragButton rightButton = getButton(views, R.id.cpp_button_right); if (rightButton != null) { rightButton.setOnDragListener(toPositionOnDragListener); } - final DragButton leftButton = getButton(root, R.id.cpp_button_left); + final DragButton leftButton = getButton(views, R.id.cpp_button_left); if (leftButton != null) { leftButton.setOnDragListener(toPositionOnDragListener); } - final DragButton equalsButton = getButton(root, R.id.cpp_button_equals); + final DragButton equalsButton = getButton(views, R.id.cpp_button_equals); if (equalsButton != null) { equalsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new EqualsDragProcessor(), dragPreferences), vibrator, preferences)); } - angleUnitsButton = getButton(root, R.id.cpp_button_6); + angleUnitsButton = getButton(views, R.id.cpp_button_6); if (angleUnitsButton != null) { angleUnitsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.AngleUnitsChanger(activity), dragPreferences), vibrator, preferences)); } - clearButton = getButton(root, R.id.cpp_button_clear); + clearButton = getButton(views, R.id.cpp_button_clear); if (clearButton != null) { clearButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.NumeralBasesChanger(activity), dragPreferences), vibrator, preferences)); } - final DragButton varsButton = getButton(root, R.id.cpp_button_vars); + final DragButton varsButton = getButton(views, R.id.cpp_button_vars); if (varsButton != null) { varsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.VarsDragProcessor(activity), dragPreferences), vibrator, preferences)); } - final DragButton functionsButton = getButton(root, R.id.cpp_button_functions); + final DragButton functionsButton = getButton(views, R.id.cpp_button_functions); if (functionsButton != null) { functionsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.FunctionsDragProcessor(activity), dragPreferences), vibrator, preferences)); } - final DragButton roundBracketsButton = getButton(root, R.id.cpp_button_round_brackets); + final DragButton roundBracketsButton = getButton(views, R.id.cpp_button_round_brackets); if (roundBracketsButton != null) { roundBracketsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.RoundBracketsDragProcessor(), dragPreferences), vibrator, preferences)); } if (layout == simple || layout == simple_mobile) { - toggleButtonDirectionText(root, R.id.cpp_button_1, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_2, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_3, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_1, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_2, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_3, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_6, false, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_7, false, DragDirection.left, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_8, false, DragDirection.left, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_6, false, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_7, false, DragDirection.left, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_8, false, DragDirection.left, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_clear, false, DragDirection.left, DragDirection.up, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_clear, false, DragDirection.left, DragDirection.up, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_4, false, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_5, false, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_4, false, DragDirection.down); + toggleButtonDirectionText(views, R.id.cpp_button_5, false, DragDirection.down); - toggleButtonDirectionText(root, R.id.cpp_button_9, false, DragDirection.left); + toggleButtonDirectionText(views, R.id.cpp_button_9, false, DragDirection.left); - toggleButtonDirectionText(root, R.id.cpp_button_multiplication, false, DragDirection.left); - toggleButtonDirectionText(root, R.id.cpp_button_plus, false, DragDirection.down, DragDirection.up); + toggleButtonDirectionText(views, R.id.cpp_button_multiplication, false, DragDirection.left); + toggleButtonDirectionText(views, R.id.cpp_button_plus, false, DragDirection.down, DragDirection.up); } CalculatorButtons.processButtons(theme, layout, root); @@ -220,8 +225,8 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh }); } - private void toggleButtonDirectionText(@Nonnull View root, int id, boolean showDirectionText, @Nonnull DragDirection... dragDirections) { - final View v = getButton(root, id); + private void toggleButtonDirectionText(@Nonnull ViewsCache views, int id, boolean showDirectionText, @Nonnull DragDirection... dragDirections) { + final View v = getButton(views, id); if (v instanceof DirectionDragButton) { final DirectionDragButton button = (DirectionDragButton) v; for (DragDirection dragDirection : dragDirections) { @@ -236,32 +241,33 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh } - private void setOnDragListeners(@Nonnull View root, @Nonnull SimpleOnDragListener.Preferences dragPreferences, @Nonnull SharedPreferences preferences) { + private void setOnDragListeners(@Nonnull ViewsCache views, @Nonnull SimpleOnDragListener.Preferences dragPreferences, @Nonnull SharedPreferences preferences) { final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(getKeyboard()), dragPreferences), vibrator, preferences); - final List dragButtonIds = new ArrayList(); + final List viewIds = getViewIds(); + for (Integer viewId : viewIds) { + final View view = views.findViewById(viewId); + if (view instanceof DragButton) { + ((DragButton) view).setOnDragListener(onDragListener); + } + } + } - for (Field field : R.id.class.getDeclaredFields()) { - int modifiers = field.getModifiers(); - if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { - try { - int viewId = field.getInt(R.id.class); - final View view = root.findViewById(viewId); - if (view instanceof DragButton) { - dragButtonIds.add(viewId); + @Nonnull + private static List getViewIds() { + if (viewIds.isEmpty()) { + for (Field field : R.id.class.getDeclaredFields()) { + int modifiers = field.getModifiers(); + if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) { + try { + viewIds.add(field.getInt(R.id.class)); + } catch (IllegalAccessException e) { + Log.e(R.id.class.getName(), e.getMessage()); } - } catch (IllegalAccessException e) { - Log.e(R.id.class.getName(), e.getMessage()); } } } - - for (Integer dragButtonId : dragButtonIds) { - final DragButton button = getButton(root, dragButtonId); - if (button != null) { - button.setOnDragListener(onDragListener); - } - } + return viewIds; } @Nonnull @@ -270,8 +276,8 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh } @Nullable - private T getButton(@Nonnull View root, int buttonId) { - return (T) root.findViewById(buttonId); + private T getButton(@Nonnull ViewsCache views, int buttonId) { + return (T) views.findViewById(buttonId); } @Nonnull diff --git a/android-app/src/main/java/org/solovyev/android/calculator/view/ViewsCache.java b/android-app/src/main/java/org/solovyev/android/calculator/view/ViewsCache.java new file mode 100644 index 00000000..c9b15bcc --- /dev/null +++ b/android-app/src/main/java/org/solovyev/android/calculator/view/ViewsCache.java @@ -0,0 +1,95 @@ +package org.solovyev.android.calculator.view; + +import android.app.Activity; +import android.support.v4.app.Fragment; +import android.util.SparseArray; +import android.view.View; + +import javax.annotation.Nonnull; + +public abstract class ViewsCache { + + @Nonnull + private final SparseArray cache = new SparseArray(); + + protected ViewsCache() { + } + + @Nonnull + public static ViewsCache forActivity(@Nonnull Activity activity) { + return new ActivityViewsCache(activity); + } + + @Nonnull + public static ViewsCache forFragment(@Nonnull Fragment fragment) { + return new FragmentViewsCache(fragment); + } + + @Nonnull + public static ViewsCache forView(@Nonnull View view) { + return new ViewViewsCache(view); + } + + public final View findViewById(int id) { + View view = cache.get(id); + if (view == null) { + view = lookupViewById(id); + if (view != null) { + cache.append(id, view); + } + } + return view; + } + + public final void clear() { + cache.clear(); + } + + protected abstract View lookupViewById(int id); + + private static final class FragmentViewsCache extends ViewsCache { + + @Nonnull + private final Fragment fragment; + + private FragmentViewsCache(@Nonnull Fragment fragment) { + this.fragment = fragment; + } + + @Override + protected View lookupViewById(int id) { + final View view = fragment.getView(); + return view != null ? view.findViewById(id) : null; + } + } + + private static final class ViewViewsCache extends ViewsCache { + + @Nonnull + private final View view; + + private ViewViewsCache(@Nonnull View view) { + this.view = view; + } + + @Override + protected View lookupViewById(int id) { + return view.findViewById(id); + } + } + + private static final class ActivityViewsCache extends ViewsCache { + + @Nonnull + private final Activity activity; + + private ActivityViewsCache(@Nonnull Activity activity) { + this.activity = activity; + } + + @Override + protected View lookupViewById(int id) { + return activity.findViewById(id); + } + } +}