summaryrefslogtreecommitdiff
path: root/core/java/android/appwidget/AppWidgetHostView.java
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2016-02-03 19:31:09 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2016-02-03 19:31:09 +0000
commit40dedd5a97b03408f37384ee0db7b9cbe5159a37 (patch)
treebd91afd594c10abf98f2e81d1f471e21077c559d /core/java/android/appwidget/AppWidgetHostView.java
parentd7595b3151f3c54809b15018ff9bd973950016de (diff)
parentdd292f4fab52f99d0b15fcf961864cd8186d662c (diff)
Merge "Added support for async inflation of RemoteViews"
Diffstat (limited to 'core/java/android/appwidget/AppWidgetHostView.java')
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java97
1 files changed, 97 insertions, 0 deletions
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 55b8f0367885..bed91ecafb96 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -29,6 +29,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -49,6 +50,8 @@ import android.widget.RemoteViews.OnClickHandler;
import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
import android.widget.TextView;
+import java.util.concurrent.Executor;
+
/**
* Provides the glue to show AppWidget views. This class offers automatic animation
* between updates, and will try recycling old views for each incoming
@@ -87,6 +90,9 @@ public class AppWidgetHostView extends FrameLayout {
Paint mOldPaint = new Paint();
private OnClickHandler mOnClickHandler;
+ private Executor mAsyncExecutor;
+ private CancellationSignal mLastExecutionSignal;
+
/**
* Create a host view. Uses default fade animations.
*/
@@ -340,6 +346,22 @@ public class AppWidgetHostView extends FrameLayout {
}
/**
+ * Sets an executor which can be used for asynchronously inflating and applying the remoteviews.
+ * @see {@link RemoteViews#applyAsync(Context, ViewGroup, RemoteViews.OnViewAppliedListener, Executor)}
+ *
+ * @param executor the executor to use or null.
+ * @hide
+ */
+ public void setAsyncExecutor(Executor executor) {
+ if (mLastExecutionSignal != null) {
+ mLastExecutionSignal.cancel();
+ mLastExecutionSignal = null;
+ }
+
+ mAsyncExecutor = executor;
+ }
+
+ /**
* Update the AppWidgetProviderInfo for this view, and reset it to the
* initial layout.
*/
@@ -380,6 +402,11 @@ public class AppWidgetHostView extends FrameLayout {
}
}
+ if (mLastExecutionSignal != null) {
+ mLastExecutionSignal.cancel();
+ mLastExecutionSignal = null;
+ }
+
if (remoteViews == null) {
if (mViewMode == VIEW_MODE_DEFAULT) {
// We've already done this -- nothing to do.
@@ -389,6 +416,10 @@ public class AppWidgetHostView extends FrameLayout {
mLayoutId = -1;
mViewMode = VIEW_MODE_DEFAULT;
} else {
+ if (mAsyncExecutor != null) {
+ inflateAsync(remoteViews);
+ return;
+ }
// Prepare a local reference to the remote Context so we're ready to
// inflate any requested LayoutParams.
mRemoteContext = getRemoteContext();
@@ -421,6 +452,10 @@ public class AppWidgetHostView extends FrameLayout {
mViewMode = VIEW_MODE_CONTENT;
}
+ applyContent(content, recycled, exception);
+ }
+
+ private void applyContent(View content, boolean recycled, Exception exception) {
if (content == null) {
if (mViewMode == VIEW_MODE_ERROR) {
// We've already done this -- nothing to do.
@@ -452,6 +487,68 @@ public class AppWidgetHostView extends FrameLayout {
}
}
+ private void inflateAsync(RemoteViews remoteViews) {
+ // Prepare a local reference to the remote Context so we're ready to
+ // inflate any requested LayoutParams.
+ mRemoteContext = getRemoteContext();
+ int layoutId = remoteViews.getLayoutId();
+
+ // If our stale view has been prepared to match active, and the new
+ // layout matches, try recycling it
+ if (layoutId == mLayoutId && mView != null) {
+ try {
+ mLastExecutionSignal = remoteViews.reapplyAsync(mContext,
+ mView,
+ mAsyncExecutor,
+ new ViewApplyListener(remoteViews, layoutId, true),
+ mOnClickHandler);
+ } catch (Exception e) {
+ // Reapply failed. Try apply
+ }
+ }
+ if (mLastExecutionSignal == null) {
+ mLastExecutionSignal = remoteViews.applyAsync(mContext,
+ this,
+ mAsyncExecutor,
+ new ViewApplyListener(remoteViews, layoutId, false),
+ mOnClickHandler);
+ }
+ }
+
+ private class ViewApplyListener implements RemoteViews.OnViewAppliedListener {
+ private final RemoteViews mViews;
+ private final boolean mIsReapply;
+ private final int mLayoutId;
+
+ public ViewApplyListener(RemoteViews views, int layoutId, boolean isReapply) {
+ mViews = views;
+ mLayoutId = layoutId;
+ mIsReapply = isReapply;
+ }
+
+ @Override
+ public void onViewApplied(View v) {
+ AppWidgetHostView.this.mLayoutId = mLayoutId;
+ mViewMode = VIEW_MODE_CONTENT;
+
+ applyContent(v, mIsReapply, null);
+ }
+
+ @Override
+ public void onError(Exception e) {
+ if (mIsReapply) {
+ // Try a fresh replay
+ mLastExecutionSignal = mViews.applyAsync(mContext,
+ AppWidgetHostView.this,
+ mAsyncExecutor,
+ new ViewApplyListener(mViews, mLayoutId, false),
+ mOnClickHandler);
+ } else {
+ applyContent(null, false, e);
+ }
+ }
+ }
+
/**
* Process data-changed notifications for the specified view in the specified
* set of {@link RemoteViews} views.