summaryrefslogtreecommitdiff
path: root/core/java/android/appwidget/AppWidgetHostView.java
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2015-12-02 14:29:27 -0800
committerSunny Goyal <sunnygoyal@google.com>2016-01-11 15:15:42 -0800
commitdd292f4fab52f99d0b15fcf961864cd8186d662c (patch)
tree84a5ddd3f92dbb697a9f310b2845ab5570bb40c9 /core/java/android/appwidget/AppWidgetHostView.java
parent5a5d6aeec0ee6b3f9ffea55a4f015edc84828b1e (diff)
Added support for async inflation of RemoteViews
When enabled, the View inflation as well as some of the drawable loading is done on the background thread. It also assumes that all the views support inflation on the background thread, which is true for the default views supported by the platform For ViewGroup opetations, it maintains a virtual view tree which is used for findViewById. The final operations are applied on the UI thread in the end. Change-Id: Ib3ce55182ec04a344f2b2513981ee03afc8fa2e8
Diffstat (limited to 'core/java/android/appwidget/AppWidgetHostView.java')
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java98
1 files changed, 98 insertions, 0 deletions
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 3219fe7fed60..bcfd1cf2fdf0 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;
@@ -38,6 +39,7 @@ import android.util.SparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Adapter;
import android.widget.AdapterView;
@@ -48,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
@@ -86,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.
*/
@@ -320,6 +327,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.
*/
@@ -360,6 +383,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.
@@ -369,6 +397,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();
@@ -401,6 +433,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.
@@ -432,6 +468,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.