Re-architecting RemoteViewsAdapter internals due to new constraints.
- Respecting the AdapterView/Adapter contract using FrameLayout notification to update individual items - Initial changes to allow for keeping (currently bitmap only) memory in check when loading numerous RemoteViews - Fixing issue with leaking activities due to extra service connection references - Fixing issue with multiple RemoteViewsAdapters being set on the same AdapterView - Fixing small issue with StackView sometimes requesting indices out of bounds - Removing background loading, reverting to previous message-queuing method (seems to be performant now) Change-Id: I42313767aa791dfe35c247c97ae5d64389e6bb4c
This commit is contained in:
@@ -4367,9 +4367,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
public void setRemoteViewsAdapter(Intent intent) {
|
||||
// Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
|
||||
// service handling the specified intent.
|
||||
Intent.FilterComparison fc = new Intent.FilterComparison(intent);
|
||||
if (mRemoteAdapter != null && fc.equals(mRemoteAdapter.getRemoteViewsServiceIntent())) {
|
||||
return;
|
||||
if (mRemoteAdapter != null) {
|
||||
Intent.FilterComparison fcNew = new Intent.FilterComparison(intent);
|
||||
Intent.FilterComparison fcOld = new Intent.FilterComparison(
|
||||
mRemoteAdapter.getRemoteViewsServiceIntent());
|
||||
if (fcNew.equals(fcOld)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, create a new RemoteViewsAdapter for binding
|
||||
|
||||
@@ -389,7 +389,7 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
|
||||
int newWindowStartUnbounded = childIndex - mActiveOffset;
|
||||
int newWindowEndUnbounded = newWindowStartUnbounded + mNumActiveViews - 1;
|
||||
int newWindowStart = Math.max(0, newWindowStartUnbounded);
|
||||
int newWindowEnd = Math.min(mAdapter.getCount(), newWindowEndUnbounded);
|
||||
int newWindowEnd = Math.min(mAdapter.getCount() - 1, newWindowEndUnbounded);
|
||||
|
||||
// This section clears out any items that are in our mActiveViews list
|
||||
// but are outside the effective bounds of our window (this is becomes an issue
|
||||
@@ -592,18 +592,18 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
|
||||
*/
|
||||
private SavedState(Parcel in) {
|
||||
super(in);
|
||||
whichChild = in.readInt();
|
||||
this.whichChild = in.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeInt(whichChild);
|
||||
out.writeInt(this.whichChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AdapterViewAnimator.SavedState{ whichChild = " + whichChild + " }";
|
||||
return "AdapterViewAnimator.SavedState{ whichChild = " + this.whichChild + " }";
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SavedState> CREATOR
|
||||
@@ -781,10 +781,13 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
|
||||
public void setRemoteViewsAdapter(Intent intent) {
|
||||
// Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
|
||||
// service handling the specified intent.
|
||||
Intent.FilterComparison fc = new Intent.FilterComparison(intent);
|
||||
if (mRemoteViewsAdapter != null &&
|
||||
fc.equals(mRemoteViewsAdapter.getRemoteViewsServiceIntent())) {
|
||||
return;
|
||||
if (mRemoteViewsAdapter != null) {
|
||||
Intent.FilterComparison fcNew = new Intent.FilterComparison(intent);
|
||||
Intent.FilterComparison fcOld = new Intent.FilterComparison(
|
||||
mRemoteViewsAdapter.getRemoteViewsServiceIntent());
|
||||
if (fcNew.equals(fcOld)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, create a new RemoteViewsAdapter for binding
|
||||
|
||||
@@ -74,6 +74,11 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
*/
|
||||
private ArrayList<Action> mActions;
|
||||
|
||||
/**
|
||||
* A class to keep track of memory usage by this RemoteViews
|
||||
*/
|
||||
private MemoryUsageCounter mMemoryUsageCounter;
|
||||
|
||||
|
||||
/**
|
||||
* This flag indicates whether this RemoteViews object is being created from a
|
||||
@@ -118,6 +123,15 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
private class SetEmptyView extends Action {
|
||||
@@ -525,7 +539,7 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int viewId;
|
||||
boolean targetBackground;
|
||||
int alpha;
|
||||
@@ -817,6 +831,35 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
throw new ActionException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
final Bitmap.Config c = b.getConfig();
|
||||
int bpp = 4;
|
||||
switch (c) {
|
||||
case ALPHA_8:
|
||||
bpp = 1;
|
||||
break;
|
||||
case RGB_565:
|
||||
case ARGB_4444:
|
||||
bpp = 2;
|
||||
break;
|
||||
case ARGB_8888:
|
||||
bpp = 4;
|
||||
break;
|
||||
}
|
||||
counter.bitmapIncrement(b.getWidth() * b.getHeight() * bpp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -854,12 +897,39 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMemoryUsageEstimate(MemoryUsageCounter counter) {
|
||||
if (nestedViews != null) {
|
||||
counter.bitmapIncrement(nestedViews.estimateBitmapMemoryUsage());
|
||||
}
|
||||
}
|
||||
|
||||
int viewId;
|
||||
RemoteViews nestedViews;
|
||||
|
||||
public final static int TAG = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple class used to keep track of memory usage in a RemoteViews.
|
||||
*
|
||||
*/
|
||||
private class MemoryUsageCounter {
|
||||
public void clear() {
|
||||
mBitmapHeapMemoryUsage = 0;
|
||||
}
|
||||
|
||||
public void bitmapIncrement(int numBytes) {
|
||||
mBitmapHeapMemoryUsage += numBytes;
|
||||
}
|
||||
|
||||
public int getBitmapHeapMemoryUsage() {
|
||||
return mBitmapHeapMemoryUsage;
|
||||
}
|
||||
|
||||
int mBitmapHeapMemoryUsage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RemoteViews object that will display the views contained
|
||||
* in the specified layout file.
|
||||
@@ -870,6 +940,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
public RemoteViews(String packageName, int layoutId) {
|
||||
mPackage = packageName;
|
||||
mLayoutId = layoutId;
|
||||
|
||||
// setup the memory usage statistics
|
||||
mMemoryUsageCounter = new MemoryUsageCounter();
|
||||
recalculateMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -920,6 +994,10 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setup the memory usage statistics
|
||||
mMemoryUsageCounter = new MemoryUsageCounter();
|
||||
recalculateMemoryUsage();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -928,6 +1006,9 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
if (mActions != null) {
|
||||
that.mActions = (ArrayList<Action>)mActions.clone();
|
||||
}
|
||||
|
||||
// update the memory usage stats of the cloned RemoteViews
|
||||
that.recalculateMemoryUsage();
|
||||
return that;
|
||||
}
|
||||
|
||||
@@ -939,7 +1020,7 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
return mLayoutId;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This flag indicates whether this RemoteViews object is being created from a
|
||||
* RemoteViewsService for use as a child of a widget collection. This flag is used
|
||||
* to determine whether or not certain features are available, in particular,
|
||||
@@ -950,6 +1031,28 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
mIsWidgetCollectionChild = isWidgetCollectionChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the memory usage statistics.
|
||||
*/
|
||||
private void recalculateMemoryUsage() {
|
||||
mMemoryUsageCounter.clear();
|
||||
|
||||
// Accumulate the memory usage for each action
|
||||
if (mActions != null) {
|
||||
final int count = mActions.size();
|
||||
for (int i= 0; i < count; ++i) {
|
||||
mActions.get(i).updateMemoryUsageEstimate(mMemoryUsageCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the bitmap heap memory usage for this RemoteViews.
|
||||
*/
|
||||
int estimateBitmapMemoryUsage() {
|
||||
return mMemoryUsageCounter.getBitmapHeapMemoryUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an action to be executed on the remote side when apply is called.
|
||||
*
|
||||
@@ -960,6 +1063,9 @@ public class RemoteViews implements Parcelable, Filter {
|
||||
mActions = new ArrayList<Action>();
|
||||
}
|
||||
mActions.add(a);
|
||||
|
||||
// update the memory usage stats
|
||||
a.updateMemoryUsageEstimate(mMemoryUsageCounter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user