目录
1.使用场景:
RemoteViews最常用的使用场景就是通知(Notification)的显示和桌面小控件的显示(Widget)
2.与View的区别:
RemoteViews与View的最主要的区别就是是否支持跨进程使用。
RemoteViews实现了Parcelable(序列化)接口,数据是支持跨进程传输的,而View没有实现Parcelable或Serializable(打包)接口,因此是不支持跨进程使用的。
View是Android UI控件的父类,也就是说它能够显示在界面上,能够让用户看到,而RemoteViews可以理解为一个工具类,它只是将数据存储并传输到另一个进程,在另一个进程中创建对应的View显示,并对View进行初始化操作。
在使用RemoteViews时不得不管在其apply,此方法是RemoteViews转化为View的纽带,源码如下:
/**
* Inflates the view hierarchy represented by this object and applies
* all of the actions.
*
* <p><strong>Caller beware: this may throw</strong>
*
* @param context Default context to use
* @param parent Parent that the resulting view hierarchy will be attached to. This method
* does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
* @return The inflated view hierarchy
*/
public View apply(Context context, ViewGroup parent) {
return apply(context, parent, null);
}
通过此方法的入参以及返回值就可以具体了解RemoteViews与View的关系了,最终可以总结为一句话“RemoteViews是支持跨进程传输数据的创建View的一个工具类”。
3.Action介绍:
从上面RemoteViews的定义知道它是支持跨进程传输的,同时View的创建都是在另外一个进程中,而我们可以在本进程中调用set方法对相关View进行初始化,但这块功能具体是怎么实现的呢?
RemoteViews的对View操作的set方法具体实现实际上就依赖Action了,在调用set方法时,会新建一个Action将操作存储下来,并将所有的Action都传到另一个进程中,在apply方法中执行所有的Action操作。
/**
* Base class for all actions that can be performed on an
* inflated view.
*
* SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
*/
private abstract static class Action implements Parcelable {
这个Action是一个抽象的基类,他有众多的派生类,来具体看看每一个派生类的作用:
- RuntimeAction
功能:在RemoteViews转换View的inflation阶段使用,也就是说在布局的xml文件转换为响应的View阶段使用,它是不支持跨进程使用的,从使用阶段上就可以看出,它只在另一个进程中使用,因此不需要支持跨进程。
/**
* Action class used during async inflation of RemoteViews. Subclasses are not parcelable.
*/
private static abstract class RuntimeAction extends Action {
@Override
public final String getActionName() {
return "RuntimeAction";
}
@Override
public final void writeToParcel(Parcel dest, int flags) {
throw new UnsupportedOperationException();
}
}
从继承关系上看是支持跨进程传输的,但是它重写了wirteToParces,并直接抛出一个异常,这就导致当跨进程传输数据时无法向通道中写入数据,从而就导致了不支持跨进程传输了。
- ActionException
作用:执行Action发生错误时抛出此异常,它只运行在另一个进程中,并且不支持跨进程。
继承关系:Action -> RuntimeAction -> ActionException
- RunnableAction
作用:异步执行Action时使用,它只运行在另一个进程中,并且不支持跨进程。
继承关系:Action -> RuntimeAction -> RunnableAction
- BitmapReflectionAction
作用:参数为Bitmap(支持跨进程传输)的操作,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> BitmapReflectionAction
例如:ImageVeiw的setImageBitmap
/**
* Equivalent to calling {@link ImageView#setImageBitmap(Bitmap)}
*
* @param viewId The id of the view whose bitmap should change
* @param bitmap The new Bitmap for the drawable
*/
public void setImageViewBitmap(int viewId, Bitmap bitmap) {
setBitmap(viewId, "setImageBitmap", bitmap);
}
- LayoutParamAction
作用:LayoutParam相关参数的设置,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> BitmapReflectionAction
3189 /**
3190 * @hide
3191 * Equivalent to calling {@link android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)}.
3192 * Only works if the {@link View#getLayoutParams()} supports margins.
3193 * Hidden for now since we don't want to support this for all different layout margins yet.
3194 *
3195 * @param viewId The id of the view to change
3196 * @param endMarginDimen a dimen resource to read the margin from or 0 to clear the margin.
3197 */
3198 public void setViewLayoutMarginEndDimen(int viewId, @DimenRes int endMarginDimen) {
3199 addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END_DIMEN,
3200 endMarginDimen));
3201 }
3202
3203 /**
3204 * Equivalent to setting {@link android.view.ViewGroup.MarginLayoutParams#bottomMargin}.
3205 *
3206 * @param bottomMarginDimen a dimen resource to read the margin from or 0 to clear the margin.
3207 * @hide
3208 */
3209 public void setViewLayoutMarginBottomDimen(int viewId, @DimenRes int bottomMarginDimen) {
3210 addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM_DIMEN,
3211 bottomMarginDimen));
3212 }
3213
3214 /**
3215 * Equivalent to setting {@link android.view.ViewGroup.LayoutParams#width}.
3216 *
3217 * @param layoutWidth one of 0, MATCH_PARENT or WRAP_CONTENT. Other sizes are not allowed
3218 * because they behave poorly when the density changes.
3219 * @hide
3220 */
3221 public void setViewLayoutWidth(int viewId, int layoutWidth) {
3222 if (layoutWidth != 0 && layoutWidth != ViewGroup.LayoutParams.MATCH_PARENT
3223 && layoutWidth != ViewGroup.LayoutParams.WRAP_CONTENT) {
3224 throw new IllegalArgumentException("Only supports 0, WRAP_CONTENT and MATCH_PARENT");
3225 }
3226 mActions.add(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_WIDTH, layoutWidth));
3227 }
- OverrideTextColorsAction(8.1版本新增)
作用:替换所有TextView中的text文字颜色,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> OverrideTextColorsAction
226 /**
227 * Override all text colors in this layout and replace them by the given text color.
228 *
229 * @param textColor The color to use.
230 *
231 * @hide
232 */
233 public void overrideTextColors(int textColor) {
234 addAction(new OverrideTextColorsAction(textColor));
235 }
- ReflectionAction(使用最多的)
作用:反射机制设置属性的Action,支持跨进程,在本进程中创建,在另外一个进程中使用(反射调用)。
继承关系:Action -> ReflectionAction
大多数的属性值都是通过这个Action设置的,例如所有的基本类型的数据
3229 /**
3230 * Call a method taking one boolean on a view in the layout for this RemoteViews.
3231 *
3232 * @param viewId The id of the view on which to call the method.
3233 * @param methodName The name of the method to call.
3234 * @param value The value to pass to the method.
3235 */
3236 public void setBoolean(int viewId, String methodName, boolean value) {
3237 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BOOLEAN, value));
3238 }
3239
3240 /**
3241 * Call a method taking one byte on a view in the layout for this RemoteViews.
3242 *
3243 * @param viewId The id of the view on which to call the method.
3244 * @param methodName The name of the method to call.
3245 * @param value The value to pass to the method.
3246 */
3247 public void setByte(int viewId, String methodName, byte value) {
3248 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BYTE, value));
3249 }
3250
3251 /**
3252 * Call a method taking one short on a view in the layout for this RemoteViews.
3253 *
3254 * @param viewId The id of the view on which to call the method.
3255 * @param methodName The name of the method to call.
3256 * @param value The value to pass to the method.
3257 */
3258 public void setShort(int viewId, String methodName, short value) {
3259 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.SHORT, value));
3260 }
3261
3262 /**
3263 * Call a method taking one int on a view in the layout for this RemoteViews.
3264 *
3265 * @param viewId The id of the view on which to call the method.
3266 * @param methodName The name of the method to call.
3267 * @param value The value to pass to the method.
3268 */
3269 public void setInt(int viewId, String methodName, int value) {
3270 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.INT, value));
3271 }
3272
3273 /**
3274 * Call a method taking one long on a view in the layout for this RemoteViews.
3275 *
3276 * @param viewId The id of the view on which to call the method.
3277 * @param methodName The name of the method to call.
3278 * @param value The value to pass to the method.
3279 */
3280 public void setLong(int viewId, String methodName, long value) {
3281 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.LONG, value));
3282 }
3283
3284 /**
3285 * Call a method taking one float on a view in the layout for this RemoteViews.
3286 *
3287 * @param viewId The id of the view on which to call the method.
3288 * @param methodName The name of the method to call.
3289 * @param value The value to pass to the method.
3290 */
3291 public void setFloat(int viewId, String methodName, float value) {
3292 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.FLOAT, value));
3293 }
3294
3295 /**
3296 * Call a method taking one double on a view in the layout for this RemoteViews.
3297 *
3298 * @param viewId The id of the view on which to call the method.
3299 * @param methodName The name of the method to call.
3300 * @param value The value to pass to the method.
3301 */
3302 public void setDouble(int viewId, String methodName, double value) {
3303 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.DOUBLE, value));
3304 }
3305
3306 /**
3307 * Call a method taking one char on a view in the layout for this RemoteViews.
3308 *
3309 * @param viewId The id of the view on which to call the method.
3310 * @param methodName The name of the method to call.
3311 * @param value The value to pass to the method.
3312 */
3313 public void setChar(int viewId, String methodName, char value) {
3314 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR, value));
3315 }
3316
3317 /**
3318 * Call a method taking one String on a view in the layout for this RemoteViews.
3319 *
3320 * @param viewId The id of the view on which to call the method.
3321 * @param methodName The name of the method to call.
3322 * @param value The value to pass to the method.
3323 */
3324 public void setString(int viewId, String methodName, String value) {
3325 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.STRING, value));
3326 }
3327
3328 /**
3329 * Call a method taking one CharSequence on a view in the layout for this RemoteViews.
3330 *
3331 * @param viewId The id of the view on which to call the method.
3332 * @param methodName The name of the method to call.
3333 * @param value The value to pass to the method.
3334 */
3335 public void setCharSequence(int viewId, String methodName, CharSequence value) {
3336 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR_SEQUENCE, value));
3337 }
3338
3339 /**
3340 * Call a method taking one Uri on a view in the layout for this RemoteViews.
3341 *
3342 * @param viewId The id of the view on which to call the method.
3343 * @param methodName The name of the method to call.
3344 * @param value The value to pass to the method.
3345 */
3346 public void setUri(int viewId, String methodName, Uri value) {
3347 if (value != null) {
3348 // Resolve any filesystem path before sending remotely
3349 value = value.getCanonicalUri();
3350 if (StrictMode.vmFileUriExposureEnabled()) {
3351 value.checkFileUriExposed("RemoteViews.setUri()");
3352 }
3353 }
3354 addAction(new ReflectionAction(viewId, methodName, ReflectionAction.URI, value));
3355 }
- ReflectionActionWithoutParams:
作用:显示前一个或后一个childVIew,支持跨进程,在本进程中创建,在另外一个进程中使用(反射调用)。
继承关系:Action -> ReflectionActionWithoutParams
例如:showNext和showPrevious
/**
* Equivalent to calling {@link AdapterViewAnimator#showNext()}
*
* @param viewId The id of the view on which to call {@link AdapterViewAnimator#showNext()}
*/
public void showNext(int viewId) {
addAction(new ReflectionActionWithoutParams(viewId, "showNext"));
}
/**
* Equivalent to calling {@link AdapterViewAnimator#showPrevious()}
*
* @param viewId The id of the view on which to call {@link AdapterViewAnimator#showPrevious()}
*/
public void showPrevious(int viewId) {
addAction(new ReflectionActionWithoutParams(viewId, "showPrevious"));
}
- SetDrawableParameters:
作用:Drawable相关参数的设置,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetDrawableParameters
/**
* @hide
* Equivalent to calling a combination of {@link Drawable#setAlpha(int)},
* {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
* and/or {@link Drawable#setLevel(int)} on the {@link Drawable} of a given
* view.
* <p>
* You can omit specific calls by marking their values with null or -1.
*
* @param viewId The id of the view that contains the target
* {@link Drawable}
* @param targetBackground If true, apply these parameters to the
* {@link Drawable} returned by
* {@link android.view.View#getBackground()}. Otherwise, assume
* the target view is an {@link ImageView} and apply them to
* {@link ImageView#getDrawable()}.
* @param alpha Specify an alpha value for the drawable, or -1 to leave
* unchanged.
* @param colorFilter Specify a color for a
* {@link android.graphics.ColorFilter} for this drawable. This will be ignored if
* {@code mode} is {@code null}.
* @param mode Specify a PorterDuff mode for this drawable, or null to leave
* unchanged.
* @param level Specify the level for the drawable, or -1 to leave
* unchanged.
*/
public void setDrawableParameters(int viewId, boolean targetBackground, int alpha,
int colorFilter, PorterDuff.Mode mode, int level) {
addAction(new SetDrawableParameters(viewId, targetBackground, alpha,
colorFilter, mode, level));
}
- SetEmptyView:
作用:添加一个Empty View,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetEmptyView
/**
* Equivalent to calling {@link AdapterView#setEmptyView(View)}
*
* @param viewId The id of the view on which to set the empty view
* @param emptyViewId The view id of the empty view
*/
public void setEmptyView(int viewId, int emptyViewId) {
addAction(new SetEmptyView(viewId, emptyViewId));
}
- SetOnClickFillInIntent:
作用:类似于ListView的onItemListener,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetOnClickFillInIntent
/**
* When using collections (eg. {@link ListView}, {@link StackView} etc.) in widgets, it is very
* costly to set PendingIntents on the individual items, and is hence not permitted. Instead
* a single PendingIntent template can be set on the collection, see {@link
* RemoteViews#setPendingIntentTemplate(int, PendingIntent)}, and the individual on-click
* action of a given item can be distinguished by setting a fillInIntent on that item. The
* fillInIntent is then combined with the PendingIntent template in order to determine the final
* intent which will be executed when the item is clicked. This works as follows: any fields
* which are left blank in the PendingIntent template, but are provided by the fillInIntent
* will be overwritten, and the resulting PendingIntent will be used. The rest
* of the PendingIntent template will then be filled in with the associated fields that are
* set in fillInIntent. See {@link Intent#fillIn(Intent, int)} for more details.
*
* @param viewId The id of the view on which to set the fillInIntent
* @param fillInIntent The intent which will be combined with the parent's PendingIntent
* in order to determine the on-click behavior of the view specified by viewId
*/
public void setOnClickFillInIntent(int viewId, Intent fillInIntent) {
addAction(new SetOnClickFillInIntent(viewId, fillInIntent));
}
- SetOnClickPendingIntent(常用):
作用:类似于View的onClickListener,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetOnClickPendingIntent
例如:SetOnClickPendingIntent
/**
* Equivalent to calling
* {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
* to launch the provided {@link PendingIntent}.
*
* When setting the on-click action of items within collections (eg. {@link ListView},
* {@link StackView} etc.), this method will not work. Instead, use {@link
* RemoteViews#setPendingIntentTemplate(int, PendingIntent)} in conjunction with
* {@link RemoteViews#setOnClickFillInIntent(int, Intent)}.
*
* @param viewId The id of the view that will trigger the {@link PendingIntent} when clicked
* @param pendingIntent The {@link PendingIntent} to send when user clicks
*/
public void setOnClickPendingIntent(int viewId, PendingIntent pendingIntent) {
addAction(new SetOnClickPendingIntent(viewId, pendingIntent));
}
- SetPendingIntentTemplate:
作用:类似于ListView的onItemListener,可以根据TAG来发送不同的Intent,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetPendingIntentTemplate
例如:SetPendingIntentTemplate
TAG:com.android.internal.R.id.fillInIntent
/**
* When using collections (eg. {@link ListView}, {@link StackView} etc.) in widgets, it is very
* costly to set PendingIntents on the individual items, and is hence not permitted. Instead
* this method should be used to set a single PendingIntent template on the collection, and
* individual items can differentiate their on-click behavior using
* {@link RemoteViews#setOnClickFillInIntent(int, Intent)}.
*
* @param viewId The id of the collection who's children will use this PendingIntent template
* when clicked
* @param pendingIntentTemplate The {@link PendingIntent} to be combined with extras specified
* by a child of viewId and executed when that child is clicked
*/
public void setPendingIntentTemplate(int viewId, PendingIntent pendingIntentTemplate) {
addAction(new SetPendingIntentTemplate(viewId, pendingIntentTemplate));
}
- SetRemoteInputsAction:
作用:支持用户输入操作,支持跨进程,在本进程中创建,在另外一个进程中使用。用户输入完成后通过Intent传回本进程或其他进程。
继承关系:Action -> SetRemoteInputsAction
/**
* @hide
*/
public void setRemoteInputs(int viewId, RemoteInput[] remoteInputs) {
mActions.add(new SetRemoteInputsAction(viewId, remoteInputs));
}
- SetRemoteViewsAdapterIntent:
作用:桌面小控件中存在ListView或GridView时使用,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetRemoteViewsAdapterIntent
/**
* Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
*
* @param appWidgetId The id of the app widget which contains the specified view. (This
* parameter is ignored in this deprecated method)
* @param viewId The id of the {@link AdapterView}
* @param intent The intent of the service which will be
* providing data to the RemoteViewsAdapter
* @deprecated This method has been deprecated. See
* {@link android.widget.RemoteViews#setRemoteAdapter(int, Intent)}
*/
@Deprecated
public void setRemoteAdapter(int appWidgetId, int viewId, Intent intent) {
setRemoteAdapter(viewId, intent);
}
/**
* Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
* Can only be used for App Widgets.
*
* @param viewId The id of the {@link AdapterView}
* @param intent The intent of the service which will be
* providing data to the RemoteViewsAdapter
*/
public void setRemoteAdapter(int viewId, Intent intent) {
addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
}
- SetRemoteViewsAdapterList:
作用:SetRemoteViewsAdapterIntent的多条功能,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> SetRemoteViewsAdapterList
/**
* Creates a simple Adapter for the viewId specified. The viewId must point to an AdapterView,
* ie. {@link ListView}, {@link GridView}, {@link StackView} or {@link AdapterViewAnimator}.
* This is a simpler but less flexible approach to populating collection widgets. Its use is
* encouraged for most scenarios, as long as the total memory within the list of RemoteViews
* is relatively small (ie. doesn't contain large or numerous Bitmaps, see {@link
* RemoteViews#setImageViewBitmap}). In the case of numerous images, the use of API is still
* possible by setting image URIs instead of Bitmaps, see {@link RemoteViews#setImageViewUri}.
*
* This API is supported in the compatibility library for previous API levels, see
* RemoteViewsCompat.
*
* @param viewId The id of the {@link AdapterView}
* @param list The list of RemoteViews which will populate the view specified by viewId.
* @param viewTypeCount The maximum number of unique layout id's used to construct the list of
* RemoteViews. This count cannot change during the life-cycle of a given widget, so this
* parameter should account for the maximum possible number of types that may appear in the
* See {@link Adapter#getViewTypeCount()}.
*
* @hide
*/
public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) {
addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount));
}
- TextViewDrawableAction:
作用:TextView设置Drawable与text距离的方法,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> TextViewDrawableAction
/**
* Equivalent to calling
* {@link TextView#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)}.
*
* @param viewId The id of the view whose text should change
* @param left The id of a drawable to place to the left of the text, or 0
* @param top The id of a drawable to place above the text, or 0
* @param right The id of a drawable to place to the right of the text, or 0
* @param bottom The id of a drawable to place below the text, or 0
*/
public void setTextViewCompoundDrawables(int viewId, int left, int top, int right, int bottom) {
addAction(new TextViewDrawableAction(viewId, false, left, top, right, bottom));
}
/**
* Equivalent to calling {@link
* TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
*
* @param viewId The id of the view whose text should change
* @param start The id of a drawable to place before the text (relative to the
* layout direction), or 0
* @param top The id of a drawable to place above the text, or 0
* @param end The id of a drawable to place after the text, or 0
* @param bottom The id of a drawable to place below the text, or 0
*/
public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) {
addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom));
}
- TextViewDrawableColorFilterAction:
作用:设置TextView中Drawable颜色滤镜,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> TextViewDrawableColorFilterAction
/**
* Equivalent to applying a color filter on one of the drawables in
* {@link android.widget.TextView#getCompoundDrawablesRelative()}.
*
* @param viewId The id of the view whose text should change.
* @param index The index of the drawable in the array of
* {@link android.widget.TextView#getCompoundDrawablesRelative()} to set the color
* filter on. Must be in [0, 3].
* @param color The color of the color filter. See
* {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
* @param mode The mode of the color filter. See
* {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
* @hide
*/
public void setTextViewCompoundDrawablesRelativeColorFilter(int viewId,
int index, int color, PorterDuff.Mode mode) {
if (index < 0 || index >= 4) {
throw new IllegalArgumentException("index must be in range [0, 3].");
}
addAction(new TextViewDrawableColorFilterAction(viewId, true, index, color, mode));
}
- TextViewSizeAction:
作用:设置TextView中text文字大小,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> TextViewSizeAction
/**
* Equivalent to calling {@link TextView#setTextSize(int, float)}
*
* @param viewId The id of the view whose text size should change
* @param units The units of size (e.g. COMPLEX_UNIT_SP)
* @param size The size of the text
*/
public void setTextViewTextSize(int viewId, int units, float size) {
addAction(new TextViewSizeAction(viewId, units, size));
}
- ViewGroupActionAdd:(8.1增加)
作用:向layout中增加RemoteViews,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> ViewGroupActionAdd
2654 /**
2655 * Equivalent to calling {@link ViewGroup#addView(View)} after inflating the
2656 * given {@link RemoteViews}. This allows users to build "nested"
2657 * {@link RemoteViews}. In cases where consumers of {@link RemoteViews} may
2658 * recycle layouts, use {@link #removeAllViews(int)} to clear any existing
2659 * children.
2660 *
2661 * @param viewId The id of the parent {@link ViewGroup} to add child into.
2662 * @param nestedView {@link RemoteViews} that describes the child.
2663 */
2664 public void addView(int viewId, RemoteViews nestedView) {
2665 addAction(nestedView == null
2666 ? new ViewGroupActionRemove(viewId)
2667 : new ViewGroupActionAdd(viewId, nestedView));
2668 }
2669
2670 /**
2671 * Equivalent to calling {@link ViewGroup#addView(View, int)} after inflating the
2672 * given {@link RemoteViews}.
2673 *
2674 * @param viewId The id of the parent {@link ViewGroup} to add the child into.
2675 * @param nestedView {@link RemoveViews} of the child to add.
2676 * @param index The position at which to add the child.
2677 *
2678 * @hide
2679 */
2680 public void addView(int viewId, RemoteViews nestedView, int index) {
2681 addAction(new ViewGroupActionAdd(viewId, nestedView, index));
2682 }
- ViewGroupActionRemove:(8.1增加)
作用:向layout中移除View,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> ViewGroupActionRemove
2684 /**
2685 * Equivalent to calling {@link ViewGroup#removeAllViews()}.
2686 *
2687 * @param viewId The id of the parent {@link ViewGroup} to remove all
2688 * children from.
2689 */
2690 public void removeAllViews(int viewId) {
2691 addAction(new ViewGroupActionRemove(viewId));
2692 }
2693
2694 /**
2695 * Removes all views in the {@link ViewGroup} specified by the {@code viewId} except for any
2696 * child that has the {@code viewIdToKeep} as its id.
2697 *
2698 * @param viewId The id of the parent {@link ViewGroup} to remove children from.
2699 * @param viewIdToKeep The id of a child that should not be removed.
2700 *
2701 * @hide
2702 */
2703 public void removeAllViewsExceptId(int viewId, int viewIdToKeep) {
2704 addAction(new ViewGroupActionRemove(viewId, viewIdToKeep));
2705 }
- ViewGroupAction:(8.1废除,使用ViewGroupActionRemove和ViewGroupActionAdd代替)
作用:向layout中移除View,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> ViewGroupAction
- ViewPaddingAction:
作用:设置View的Padding值,支持跨进程,在本进程中创建,在另外一个进程中使用。
继承关系:Action -> ViewPaddingAction
/**
* Equivalent to calling {@link android.view.View#setPadding(int, int, int, int)}.
*
* @param viewId The id of the view to change
* @param left the left padding in pixels
* @param top the top padding in pixels
* @param right the right padding in pixels
* @param bottom the bottom padding in pixels
*/
public void setViewPadding(int viewId, int left, int top, int right, int bottom) {
addAction(new ViewPaddingAction(viewId, left, top, right, bottom));
}
4.Action怎么转化为View的流程:
在系统需要将RemoteViews转化为View时,会调用其隐藏的apply方法,当然APP应用也可以使用反射的方法调用(9.0版本之前)。此时会执行到getRemoteViewsToApply方法中,获取当前需要显示横向的还是纵向的RemoteViews,之后在根据这个RemoteViews生成响应的ViewTree(View树性结构),也就是执行LayoutInflater的infalte方法将对应的布局文件的ID转化为ViewTree,有了ViewTree后就要对每个View进行初始化操作,此时就执行到了performApply方法。在此方法中会遍历所有的Action,并执行其apply方法,这样RemoteViews就转成了我们在UI上看见的画面,并完成了初始化操作。
以ReflectionAction举例具体说明Action的执行过程。在创建ReflectionAction时会初始化其成员变量:viewId、methodName、type和value等值,在apply方法中根据viewId寻找响应的View,根据methodname寻找响应的方法,之后利用反色机制将value值更新到View上,这样此Action就执行完了。
源码如下:
1510 @Override
1511 public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
1512 final View view = root.findViewById(viewId);
1513 if (view == null) return;
1514
1515 Class<?> param = getParameterType();
1516 if (param == null) {
1517 throw new ActionException("bad type: " + this.type);
1518 }
1519
1520 try {
1521 getMethod(view, this.methodName, param).invoke(view, wrapArg(this.value));
1522 } catch (ActionException e) {
1523 throw e;
1524 } catch (Exception ex) {
1525 throw new ActionException(ex);
1526 }
1527 }
5.总结:
- RemoteViews是一个支持跨进程创建并更新View的工具类;
- RemoteViews是一个学习Parceable跨进程传输数据的工具;
- RemoteViews创建View和更新View都是在另一个进程中进行的,在本进程中主要是将Action等数据存储后等待传输到另外一个进程中。
本人浅见,欢迎斧正!