diff options
| author | Sunny Goyal <sunnygoyal@google.com> | 2016-02-03 19:31:09 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-02-03 19:31:09 +0000 |
| commit | 40dedd5a97b03408f37384ee0db7b9cbe5159a37 (patch) | |
| tree | bd91afd594c10abf98f2e81d1f471e21077c559d /core/java/android/appwidget/AppWidgetHostView.java | |
| parent | d7595b3151f3c54809b15018ff9bd973950016de (diff) | |
| parent | dd292f4fab52f99d0b15fcf961864cd8186d662c (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.java | 97 |
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. |
