Merge "Fixing partiallyUpdateAppWidget to cache the new changes" into jb-mr1-dev
This commit is contained in:
@@ -436,10 +436,9 @@ public class AppWidgetManager {
|
||||
*
|
||||
* This update differs from {@link #updateAppWidget(int[], RemoteViews)} in that the
|
||||
* RemoteViews object which is passed is understood to be an incomplete representation of the
|
||||
* widget, and hence is not cached by the AppWidgetService. Note that because these updates are
|
||||
* not cached, any state that they modify that is not restored by restoreInstanceState will not
|
||||
* persist in the case that the widgets are restored using the cached version in
|
||||
* AppWidgetService.
|
||||
* widget, and hence does not replace the cached representation of the widget. As of API
|
||||
* level 17, the new properties set within the views objects will be appended to the cached
|
||||
* representation of the widget, and hence will persist.
|
||||
*
|
||||
* Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)},
|
||||
* {@link RemoteViews#setScrollPosition(int, int)} and similar commands.
|
||||
|
||||
@@ -52,6 +52,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
/**
|
||||
@@ -187,6 +188,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
public abstract void apply(View root, ViewGroup rootParent,
|
||||
OnClickHandler handler) throws ActionException;
|
||||
|
||||
public static final int MERGE_REPLACE = 0;
|
||||
public static final int MERGE_APPEND = 1;
|
||||
public static final int MERGE_IGNORE = 2;
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@@ -203,6 +208,60 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
public void setBitmapCache(BitmapCache bitmapCache) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public int mergeBehavior() {
|
||||
return MERGE_REPLACE;
|
||||
}
|
||||
|
||||
public abstract String getActionName();
|
||||
|
||||
public String getUniqueKey() {
|
||||
return (getActionName() + viewId);
|
||||
}
|
||||
|
||||
int viewId;
|
||||
}
|
||||
|
||||
public void mergeRemoteViews(RemoteViews newRv) {
|
||||
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
|
||||
// reference the bitmap cache. We don't want to modify the object as it may need to
|
||||
// be merged and applied multiple times.
|
||||
Parcel p = Parcel.obtain();
|
||||
newRv.writeToParcel(p, 0);
|
||||
RemoteViews copy = new RemoteViews(p);
|
||||
|
||||
HashMap<String, Action> map = new HashMap<String, Action>();
|
||||
if (mActions == null) {
|
||||
mActions = new ArrayList<Action>();
|
||||
}
|
||||
|
||||
int count = mActions.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Action a = mActions.get(i);
|
||||
map.put(a.getUniqueKey(), a);
|
||||
}
|
||||
|
||||
ArrayList<Action> newActions = copy.mActions;
|
||||
if (newActions == null) return;
|
||||
count = newActions.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Action a = newActions.get(i);
|
||||
String key = newActions.get(i).getUniqueKey();
|
||||
int mergeBehavior = map.get(key).mergeBehavior();
|
||||
if (map.containsKey(key) && mergeBehavior == Action.MERGE_REPLACE) {
|
||||
mActions.remove(map.get(key));
|
||||
map.remove(key);
|
||||
}
|
||||
|
||||
// If the merge behavior is ignore, we don't bother keeping the extra action
|
||||
if (mergeBehavior == Action.MERGE_REPLACE || mergeBehavior == Action.MERGE_APPEND) {
|
||||
mActions.add(a);
|
||||
}
|
||||
}
|
||||
|
||||
// Because pruning can remove the need for bitmaps, we reconstruct the bitmap cache
|
||||
mBitmapCache = new BitmapCache();
|
||||
setBitmapCache(mBitmapCache);
|
||||
}
|
||||
|
||||
private class SetEmptyView extends Action {
|
||||
@@ -239,6 +298,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
|
||||
adapterView.setEmptyView(emptyView);
|
||||
}
|
||||
|
||||
public String getActionName() {
|
||||
return "SetEmptyView";
|
||||
}
|
||||
}
|
||||
|
||||
private class SetOnClickFillInIntent extends Action {
|
||||
@@ -316,7 +379,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "SetOnClickFillInIntent";
|
||||
}
|
||||
|
||||
Intent fillInIntent;
|
||||
|
||||
public final static int TAG = 9;
|
||||
@@ -399,7 +465,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "SetPendingIntentTemplate";
|
||||
}
|
||||
|
||||
PendingIntent pendingIntentTemplate;
|
||||
|
||||
public final static int TAG = 8;
|
||||
@@ -453,7 +522,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "SetRemoteViewsAdapterIntent";
|
||||
}
|
||||
|
||||
Intent intent;
|
||||
|
||||
public final static int TAG = 10;
|
||||
@@ -539,7 +611,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "SetOnClickPendingIntent";
|
||||
}
|
||||
|
||||
PendingIntent pendingIntent;
|
||||
|
||||
public final static int TAG = 1;
|
||||
@@ -625,7 +700,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "SetDrawableParameters";
|
||||
}
|
||||
|
||||
boolean targetBackground;
|
||||
int alpha;
|
||||
int colorFilter;
|
||||
@@ -636,7 +714,6 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
|
||||
private class ReflectionActionWithoutParams extends Action {
|
||||
int viewId;
|
||||
String methodName;
|
||||
|
||||
public final static int TAG = 5;
|
||||
@@ -688,6 +765,19 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
throw new ActionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public int mergeBehavior() {
|
||||
// we don't need to build up showNext or showPrevious calls
|
||||
if (methodName.equals("showNext") || methodName.equals("showPrevious")) {
|
||||
return MERGE_IGNORE;
|
||||
} else {
|
||||
return MERGE_REPLACE;
|
||||
}
|
||||
}
|
||||
|
||||
public String getActionName() {
|
||||
return "ReflectionActionWithoutParams";
|
||||
}
|
||||
}
|
||||
|
||||
private static class BitmapCache {
|
||||
@@ -755,7 +845,6 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
|
||||
private class BitmapReflectionAction extends Action {
|
||||
int bitmapId;
|
||||
int viewId;
|
||||
Bitmap bitmap;
|
||||
String methodName;
|
||||
|
||||
@@ -794,6 +883,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
bitmapId = bitmapCache.getBitmapId(bitmap);
|
||||
}
|
||||
|
||||
public String getActionName() {
|
||||
return "BitmapReflectionAction";
|
||||
}
|
||||
|
||||
public final static int TAG = 12;
|
||||
}
|
||||
|
||||
@@ -814,11 +907,12 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
static final int STRING = 9;
|
||||
static final int CHAR_SEQUENCE = 10;
|
||||
static final int URI = 11;
|
||||
// BITMAP actions are never stored in the list of actions. They are only used locally
|
||||
// to implement BitmapReflectionAction, which eliminates duplicates using BitmapCache.
|
||||
static final int BITMAP = 12;
|
||||
static final int BUNDLE = 13;
|
||||
static final int INTENT = 14;
|
||||
|
||||
int viewId;
|
||||
String methodName;
|
||||
int type;
|
||||
Object value;
|
||||
@@ -1041,20 +1135,20 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
|
||||
// We currently only calculate Bitmap memory usage
|
||||
switch (this.type) {
|
||||
case BITMAP:
|
||||
if (this.value != null) {
|
||||
final Bitmap b = (Bitmap) this.value;
|
||||
counter.addBitmapMemory(b);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
public int mergeBehavior() {
|
||||
// smoothScrollBy is cumulative, everything else overwites.
|
||||
if (methodName.equals("smoothScrollBy")) {
|
||||
return MERGE_APPEND;
|
||||
} else {
|
||||
return MERGE_REPLACE;
|
||||
}
|
||||
}
|
||||
|
||||
public String getActionName() {
|
||||
// Each type of reflection action corresponds to a setter, so each should be seen as
|
||||
// unique from the standpoint of merging.
|
||||
return "ReflectionAction" + this.methodName + this.type;
|
||||
}
|
||||
}
|
||||
|
||||
private void configureRemoteViewsAsChild(RemoteViews rv) {
|
||||
@@ -1131,7 +1225,14 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "ViewGroupAction" + this.nestedViews == null ? "Remove" : "Add";
|
||||
}
|
||||
|
||||
public int mergeBehavior() {
|
||||
return MERGE_APPEND;
|
||||
}
|
||||
|
||||
RemoteViews nestedViews;
|
||||
|
||||
public final static int TAG = 4;
|
||||
@@ -1182,7 +1283,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "TextViewDrawableAction";
|
||||
}
|
||||
|
||||
boolean isRelative = false;
|
||||
int d1, d2, d3, d4;
|
||||
|
||||
@@ -1220,7 +1324,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
target.setTextSize(units, size);
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "TextViewSizeAction";
|
||||
}
|
||||
|
||||
int units;
|
||||
float size;
|
||||
|
||||
@@ -1264,7 +1371,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
target.setPadding(left, top, right, bottom);
|
||||
}
|
||||
|
||||
int viewId;
|
||||
public String getActionName() {
|
||||
return "ViewPaddingAction";
|
||||
}
|
||||
|
||||
int left, top, right, bottom;
|
||||
|
||||
public final static int TAG = 14;
|
||||
|
||||
@@ -980,9 +980,13 @@ class AppWidgetServiceImpl {
|
||||
// drop unbound appWidgetIds (shouldn't be possible under normal circumstances)
|
||||
if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) {
|
||||
|
||||
// We do not want to save this RemoteViews
|
||||
if (!isPartialUpdate)
|
||||
if (!isPartialUpdate) {
|
||||
// For a full update we replace the RemoteViews completely.
|
||||
id.views = views;
|
||||
} else {
|
||||
// For a partial update, we merge the new RemoteViews with the old.
|
||||
id.views.mergeRemoteViews(views);
|
||||
}
|
||||
|
||||
// is anyone listening?
|
||||
if (id.host.callbacks != null) {
|
||||
|
||||
Reference in New Issue
Block a user