summaryrefslogtreecommitdiffstats
path: root/core/java/android/widget/RemoteViews.java
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2013-07-22 13:02:02 -0700
committerRomain Guy <romainguy@google.com>2013-07-22 13:02:02 -0700
commite4d4e20e8f84d53b4b7198300baaf3e21ff9be58 (patch)
treea150da25db0f8a3ba9cf43848afe766b2ccc265c /core/java/android/widget/RemoteViews.java
parent4a8baef3f56042ab4592db030c61af0a4c632d15 (diff)
downloadframeworks_base-e4d4e20e8f84d53b4b7198300baaf3e21ff9be58.zip
frameworks_base-e4d4e20e8f84d53b4b7198300baaf3e21ff9be58.tar.gz
frameworks_base-e4d4e20e8f84d53b4b7198300baaf3e21ff9be58.tar.bz2
Cache reflection lookups
This change also cleanups the code a little bit. Caching lookups not only speed things up but it also avoids unnecessary allocations. Change-Id: Ie3d1ae106d32b3b5f2c5d33b6318ed93cd9e27f9
Diffstat (limited to 'core/java/android/widget/RemoteViews.java')
-rw-r--r--core/java/android/widget/RemoteViews.java202
1 files changed, 100 insertions, 102 deletions
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 07e66b7..29b4708 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -37,6 +37,7 @@ import android.os.Parcelable;
import android.os.StrictMode;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.LayoutInflater.Filter;
@@ -136,6 +137,16 @@ public class RemoteViews implements Parcelable, Filter {
private static final OnClickHandler DEFAULT_ON_CLICK_HANDLER = new OnClickHandler();
+ private static final Object sMethodsLock = new Object[0];
+ private static final ArrayMap<Class<? extends View>, ArrayMap<String, Method>> sMethods =
+ new ArrayMap<Class<? extends View>, ArrayMap<String, Method>>();
+ private static final ThreadLocal<Object[]> sInvokeArgsTls = new ThreadLocal<Object[]>() {
+ @Override
+ protected Object[] initialValue() {
+ return new Object[1];
+ }
+ };
+
/**
* This annotation indicates that a subclass of View is alllowed to be used
* with the {@link RemoteViews} mechanism.
@@ -206,9 +217,8 @@ public class RemoteViews implements Parcelable, Filter {
* Overridden by each class to report on it's own memory usage
*/
public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
- // We currently only calculate Bitmap memory usage, so by default, don't do anything
- // here
- return;
+ // We currently only calculate Bitmap memory usage, so by default,
+ // don't do anything here
}
public void setBitmapCache(BitmapCache bitmapCache) {
@@ -346,7 +356,7 @@ public class RemoteViews implements Parcelable, Filter {
}
if (target == root) {
target.setTagInternal(com.android.internal.R.id.fillInIntent, fillInIntent);
- } else if (target != null && fillInIntent != null) {
+ } else if (fillInIntent != null) {
OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
// Insure that this view is a child of an AdapterView
@@ -372,16 +382,7 @@ public class RemoteViews implements Parcelable, Filter {
PendingIntent pendingIntent = (PendingIntent) parent.getTag();
- final float appScale = v.getContext().getResources()
- .getCompatibilityInfo().applicationScale;
- final int[] pos = new int[2];
- v.getLocationOnScreen(pos);
-
- final Rect rect = new Rect();
- rect.left = (int) (pos[0] * appScale + 0.5f);
- rect.top = (int) (pos[1] * appScale + 0.5f);
- rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
- rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
+ final Rect rect = getSourceBounds(v);
fillInIntent.setSourceBounds(rect);
handler.onClickHandler(v, pendingIntent, fillInIntent);
@@ -452,16 +453,7 @@ public class RemoteViews implements Parcelable, Filter {
}
if (fillInIntent == null) return;
- final float appScale = view.getContext().getResources()
- .getCompatibilityInfo().applicationScale;
- final int[] pos = new int[2];
- view.getLocationOnScreen(pos);
-
- final Rect rect = new Rect();
- rect.left = (int) (pos[0] * appScale + 0.5f);
- rect.top = (int) (pos[1] * appScale + 0.5f);
- rect.right = (int) ((pos[0] + view.getWidth()) * appScale + 0.5f);
- rect.bottom = (int) ((pos[1] + view.getHeight()) * appScale + 0.5f);
+ final Rect rect = getSourceBounds(view);
final Intent intent = new Intent();
intent.setSourceBounds(rect);
@@ -679,33 +671,22 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- if (target != null) {
- // If the pendingIntent is null, we clear the onClickListener
- OnClickListener listener = null;
- if (pendingIntent != null) {
- listener = new OnClickListener() {
- public void onClick(View v) {
- // Find target view location in screen coordinates and
- // fill into PendingIntent before sending.
- final float appScale = v.getContext().getResources()
- .getCompatibilityInfo().applicationScale;
- final int[] pos = new int[2];
- v.getLocationOnScreen(pos);
-
- final Rect rect = new Rect();
- rect.left = (int) (pos[0] * appScale + 0.5f);
- rect.top = (int) (pos[1] * appScale + 0.5f);
- rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
- rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
+ // If the pendingIntent is null, we clear the onClickListener
+ OnClickListener listener = null;
+ if (pendingIntent != null) {
+ listener = new OnClickListener() {
+ public void onClick(View v) {
+ // Find target view location in screen coordinates and
+ // fill into PendingIntent before sending.
+ final Rect rect = getSourceBounds(v);
- final Intent intent = new Intent();
- intent.setSourceBounds(rect);
- handler.onClickHandler(v, pendingIntent, intent);
- }
- };
- }
- target.setOnClickListener(listener);
+ final Intent intent = new Intent();
+ intent.setSourceBounds(rect);
+ handler.onClickHandler(v, pendingIntent, intent);
+ }
+ };
}
+ target.setOnClickListener(listener);
}
public String getActionName() {
@@ -717,6 +698,64 @@ public class RemoteViews implements Parcelable, Filter {
public final static int TAG = 1;
}
+ private static Rect getSourceBounds(View v) {
+ final float appScale = v.getContext().getResources()
+ .getCompatibilityInfo().applicationScale;
+ final int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+
+ final Rect rect = new Rect();
+ rect.left = (int) (pos[0] * appScale + 0.5f);
+ rect.top = (int) (pos[1] * appScale + 0.5f);
+ rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
+ rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
+ return rect;
+ }
+
+ private static Method getMethod(View view, String methodName, Class<?> paramType) {
+ Method method;
+ Class<? extends View> klass = view.getClass();
+
+ synchronized (sMethodsLock) {
+ ArrayMap<String, Method> methods = sMethods.get(klass);
+ if (methods == null) {
+ methods = new ArrayMap<String, Method>();
+ sMethods.put(klass, methods);
+ }
+
+ method = methods.get(methodName);
+ if (method == null) {
+ try {
+ method = klass.getMethod(methodName, paramType);
+ } catch (NoSuchMethodException ex) {
+ throw new ActionException("view: " + klass.getName() + " doesn't have method: "
+ + methodName + getParameters(paramType));
+ }
+
+ if (!method.isAnnotationPresent(RemotableViewMethod.class)) {
+ throw new ActionException("view: " + klass.getName()
+ + " can't use method with RemoteViews: "
+ + methodName + getParameters(paramType));
+ }
+
+ methods.put(methodName, method);
+ }
+ }
+
+ return method;
+ }
+
+ private static String getParameters(Class<?> paramType) {
+ if (paramType == null) return "()";
+ return "(" + paramType + ")";
+ }
+
+ private static Object[] wrapArg(Object value) {
+ Object[] args = sInvokeArgsTls.get();
+ args[0] = value;
+ return args;
+ }
+
/**
* Equivalent to calling a combination of {@link Drawable#setAlpha(int)},
* {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
@@ -836,28 +875,10 @@ public class RemoteViews implements Parcelable, Filter {
final View view = root.findViewById(viewId);
if (view == null) return;
- Class klass = view.getClass();
- Method method;
- try {
- method = klass.getMethod(this.methodName);
- } catch (NoSuchMethodException ex) {
- throw new ActionException("view: " + klass.getName() + " doesn't have method: "
- + this.methodName + "()");
- }
-
- if (!method.isAnnotationPresent(RemotableViewMethod.class)) {
- throw new ActionException("view: " + klass.getName()
- + " can't use method with RemoteViews: "
- + this.methodName + "()");
- }
-
try {
- //noinspection ConstantIfStatement
- if (false) {
- Log.d(LOG_TAG, "view: " + klass.getName() + " calling method: "
- + this.methodName + "()");
- }
- method.invoke(view);
+ getMethod(view, this.methodName, null).invoke(view);
+ } catch (ActionException e) {
+ throw e;
} catch (Exception ex) {
throw new ActionException(ex);
}
@@ -1157,7 +1178,7 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- private Class getParameterType() {
+ private Class<?> getParameterType() {
switch (this.type) {
case BOOLEAN:
return boolean.class;
@@ -1197,37 +1218,16 @@ public class RemoteViews implements Parcelable, Filter {
final View view = root.findViewById(viewId);
if (view == null) return;
- Class param = getParameterType();
+ Class<?> param = getParameterType();
if (param == null) {
throw new ActionException("bad type: " + this.type);
}
- Class klass = view.getClass();
- Method method;
- try {
- method = klass.getMethod(this.methodName, getParameterType());
- }
- catch (NoSuchMethodException ex) {
- throw new ActionException("view: " + klass.getName() + " doesn't have method: "
- + this.methodName + "(" + param.getName() + ")");
- }
-
- if (!method.isAnnotationPresent(RemotableViewMethod.class)) {
- throw new ActionException("view: " + klass.getName()
- + " can't use method with RemoteViews: "
- + this.methodName + "(" + param.getName() + ")");
- }
-
try {
- //noinspection ConstantIfStatement
- if (false) {
- Log.d(LOG_TAG, "view: " + klass.getName() + " calling method: "
- + this.methodName + "(" + param.getName() + ") with "
- + (this.value == null ? "null" : this.value.getClass().getName()));
- }
- method.invoke(view, this.value);
- }
- catch (Exception ex) {
+ getMethod(view, this.methodName, param).invoke(view, wrapArg(this.value));
+ } catch (ActionException e) {
+ throw e;
+ } catch (Exception ex) {
throw new ActionException(ex);
}
}
@@ -1323,7 +1323,7 @@ public class RemoteViews implements Parcelable, Filter {
}
public String getActionName() {
- return "ViewGroupAction" + this.nestedViews == null ? "Remove" : "Add";
+ return "ViewGroupAction" + (nestedViews == null ? "Remove" : "Add");
}
public int mergeBehavior() {
@@ -1370,7 +1370,6 @@ public class RemoteViews implements Parcelable, Filter {
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final Context context = root.getContext();
final TextView target = (TextView) root.findViewById(viewId);
if (target == null) return;
if (isRelative) {
@@ -1415,7 +1414,6 @@ public class RemoteViews implements Parcelable, Filter {
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final Context context = root.getContext();
final TextView target = (TextView) root.findViewById(viewId);
if (target == null) return;
target.setTextSize(units, size);
@@ -1462,7 +1460,6 @@ public class RemoteViews implements Parcelable, Filter {
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final Context context = root.getContext();
final View target = root.findViewById(viewId);
if (target == null) return;
target.setPadding(left, top, right, bottom);
@@ -1494,6 +1491,7 @@ public class RemoteViews implements Parcelable, Filter {
return mMemoryUsage;
}
+ @SuppressWarnings("deprecation")
public void addBitmapMemory(Bitmap b) {
final Bitmap.Config c = b.getConfig();
// If we don't know, be pessimistic and assume 4
@@ -1597,7 +1595,7 @@ public class RemoteViews implements Parcelable, Filter {
if (mode == MODE_NORMAL) {
mPackage = parcel.readString();
mLayoutId = parcel.readInt();
- mIsWidgetCollectionChild = parcel.readInt() == 1 ? true : false;
+ mIsWidgetCollectionChild = parcel.readInt() == 1;
int count = parcel.readInt();
if (count > 0) {