日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

完全理解Android中的RemoteViews

發(fā)布時間:2024/7/19 Android 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 完全理解Android中的RemoteViews 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、什么是RemoteViews

RemoteViews翻譯過來就是遠(yuǎn)程視圖.顧名思義,RemoteViews不是當(dāng)前進(jìn)程的View,是屬于SystemServer進(jìn)程.應(yīng)用程序與RemoteViews之間依賴Binder實現(xiàn)了進(jìn)程間通信.

二、RemoteViews的用法

RemoteViews使用最多的場合是通知欄和桌面小插件. 以通知欄為例,講解下它的用法.

1、新建一個Notification

這里要注意是在android3.0之前都是使用如下的形式構(gòu)建一個Notification

// 1.新建一個Notification對象 Notification mNotification = new Notification(); // 2.添加屬性,比如標(biāo)題、內(nèi)容、優(yōu)先級、圖片等 mNotification.tickerText = "這是通知欄的標(biāo)題"; mNotification.icon = R.drawable.ic_launcher; mNotification.flags=Notification.FLAG_NO_CLEAR; mNotification.setLatestEventInfo(this, "這是內(nèi)容", "這是標(biāo)題", null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在3.0之后官方推薦使用建造者模式創(chuàng)建Notification.

Notification mNotification = new Notification.Builder(this) .setContentTitle("這是標(biāo)題 ") .setContentText("這是內(nèi)容") .setSmallIcon(R.drawable.ic_launcher) .build();
  • 1
  • 2
  • 3
  • 4
  • 5

Notification有很多屬性,這里列舉一些

- setContentTitle 設(shè)置標(biāo)題 - setContentText 設(shè)置內(nèi)容 - setLargeIcon 設(shè)置通知欄大圖標(biāo) - setSmallIcon 設(shè)置通知欄小圖標(biāo) - setContent 設(shè)置RemoteViews - setContentIntent 當(dāng)通知條目被點擊,就執(zhí)行這個被設(shè)置的Intent. - setDeleteIntent 當(dāng)用戶點擊"Clear All Notifications"按鈕區(qū)刪除所有的通知的時候,這個被設(shè)置的Intent被執(zhí)行 - setLights 設(shè)置閃光燈 - setSound 設(shè)置聲音 - setPriority 設(shè)置優(yōu)先級

2、設(shè)置Notification的RemoteViews

如果要給通知欄使用自定義布局就要使用RemoteViews了,傳入包名和相應(yīng)的布局.

RemoteViews mRemoteViews=new RemoteViews("com.example.remoteviewdemo", R.layout.remoteview_layout);
  • 1

然后通過setContent()傳入RemoteViews 對象即可.

這里順便講一下PendingIntent,PendingIntent是”延遲意圖”的意思,就是當(dāng)滿足某一條件時出觸發(fā)這個Intent.通過PendingIntent的getActivity、getBroadcast、getService等分別構(gòu)建一個打開對應(yīng)組件的延遲Intent.?
傳入四個參數(shù),context、intent、requestCode(自定義)、flag.

Intent intent=new Intent(MainActivity.this,MainActivity.class); PendingIntent mPendingIntent=PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • 1
  • 2

PendingIntent有4種flag.

- FLAG_ONE_SHOT 只執(zhí)行一次 - FLAG_NO_CREATE 若描述的Intent不存在則返回NULL值 - FLAG_CANCEL_CURRENT 如果描述的PendingIntent已經(jīng)存在,則在產(chǎn)生新的Intent之前會先取消掉當(dāng)前的 - FLAG_UPDATE_CURRENT 總是執(zhí)行,這個flag用的最多

3、獲取通知管理者

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  • 1

4、彈出通知

調(diào)用notify方法,傳入一個id(自定義)和通知實例即可.

manager.notify(1, mNotification);
  • 1

5、例子

我用一個按鈕彈出通知,點擊這個通知時進(jìn)入到該Activity

public class MainActivity extends Activity { private NotificationManager manager; private Notification mNotification; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //1.創(chuàng)建RemoteViews實例 RemoteViews mRemoteViews=new RemoteViews("com.example.remoteviewdemo", R.layout.remoteview_layout); //2.構(gòu)建一個打開Activity的PendingIntent Intent intent=new Intent(MainActivity.this,MainActivity.class); PendingIntent mPendingIntent=PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); //3.創(chuàng)建一個Notification mNotification = new Notification.Builder(this) .setSmallIcon(R.drawable.ic_launcher) .setContentIntent(mPendingIntent) .setContent(mRemoteViews) .build(); //4.獲取NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Button button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //彈出通知 manager.notify(1, mNotification); } }); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

如下圖

6、改變RemoteViews的布局

RemoteViews并不能直接獲得控件實例,然后對控件進(jìn)行操作.它提供了?
setTextViewText(viewId, text)、setImageViewResource(viewId, srcId)等方法進(jìn)行操作,傳入控件id和相應(yīng)的修改內(nèi)容.?
列舉一下常用的屬性

- setTextViewText(viewId, text) 設(shè)置文本 - setTextColor(viewId, color) 設(shè)置文本顏色 - setTextViewTextSize(viewId, units, size) 設(shè)置文本大小 - setImageViewBitmap(viewId, bitmap) 設(shè)置圖片 - setImageViewResource(viewId, srcId) 根據(jù)圖片資源設(shè)置圖片 - setViewPadding(viewId, left, top, right, bottom) 設(shè)置Padding間距 - setOnClickPendingIntent(viewId, pendingIntent) 設(shè)置點擊事件

我這里就以setTextViewText改變文本的屬性來講解改變RemoteViews的原理.?
我在原來的代碼上加上一個按鈕點擊改變內(nèi)容

Button button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mRemoteViews.setTextViewText(R.id.remote_content, "改變了內(nèi)容"); manager.notify(1, mNotification); } });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

看下效果

三、RemoteViews的改變原理

1.setTextViewText方法代碼如下

public class RemoteViews implements Parcelable, Filter { ...... public void setTextViewText(int viewId, CharSequence text) { setCharSequence(viewId, "setText", text); } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.調(diào)用了setCharSequence方法

public class RemoteViews implements Parcelable, Filter { ...... public void setCharSequence(int viewId, String methodName, CharSequence value) { addAction(new ReflectionAction(viewId, methodName, ReflectionAction.CHAR_SEQUENCE, value)); } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3.在setCharSequence方法里調(diào)用了addAction方法,傳入一個ReflectionAction實例,ReflectionAction繼承自Action,它是用反射調(diào)用的

private final class ReflectionAction extends Action { ...... ReflectionAction(int viewId, String methodName, int type, Object value) { this.viewId = viewId; this.methodName = methodName; this.type = type; this.value = value; } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

4.看下addAction方法,用了一個集合來保存Action實例,然后更新已使用內(nèi)存的統(tǒng)計情況

public class RemoteViews implements Parcelable, Filter { ...... private void addAction(Action a) { if (mActions == null) { mActions = new ArrayList<Action>(); } //添加Action mActions.add(a); // 更新已使用內(nèi)存的統(tǒng)計情況 a.updateMemoryUsageEstimate(mMemoryUsageCounter); } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

這一步之后,會調(diào)用

manager.notify(1, mNotification);
  • 1

來更新,追蹤這個notify方法.

public class NotificationManager { ...... public void notify(String tag, int id, Notification notification) { ...... INotificationManager service = getService(); try { service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id, stripped, idOut, UserHandle.myUserId()); ...... } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

5.上面會調(diào)用getService方法返回INotificationManager這個系統(tǒng)服務(wù),它是在SystemServer進(jìn)程添加的.然后該服務(wù)調(diào)用 enqueueNotificationWithTag方法最后層層調(diào)用到

public class NotificationManagerService extends INotificationManager.Stub { ...... StatusBarNotification n = new StatusBarNotification(pkg, id, tag, r.uid, r.initialPid, notification); try { mStatusBar.updateNotification(r.statusBarKey, n) } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

新建了StatusBarNotification實例,然后調(diào)用updateNotification方法.?
這個方法會進(jìn)入到

public class PhoneStatusBar extends StatusBar { ...... public void updateNotification(IBinder key, StatusBarNotification notification) { ...... final RemoteViews contentView = notification.notification.contentView; ...... contentView.reapply(mContext, oldEntry.content); ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

會調(diào)用StatusBarNotification 的notification.contentView返回RemoteViews 對象,然后調(diào)用reapply方法.

6.回到RemoteViews 的reapply方法

public class RemoteViews implements Parcelable, Filter { ...... public void reapply(Context context, View v, OnClickHandler handler) { RemoteViews rvToApply = getRemoteViewsToApply(context); ...... rvToApply.performApply(v, (ViewGroup) v.getParent(), handler); } private void performApply(View v, ViewGroup parent, OnClickHandler handler) { if (mActions != null) { handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler; final int count = mActions.size(); for (int i = 0; i < count; i++) { Action a = mActions.get(i); //調(diào)用apply方法 a.apply(v, parent, handler); } } } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

最終調(diào)用apply方法,在這里加載新的布局,RemoteViews就是這么完成的.

public class RemoteViews implements Parcelable, Filter { ...... public View apply(Context context, ViewGroup parent, OnClickHandler handler) { RemoteViews rvToApply = getRemoteViewsToApply(context); View result; LayoutInflater inflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); ...... //加載布局 result = inflater.inflate(rvToApply.getLayoutId(), parent, false); rvToApply.performApply(result, parent, handler); return result; } ...... }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

總結(jié)

RemoteViews運行在SystemServer進(jìn)程,更新RemoteViews要通過Binder獲取到對應(yīng)的服務(wù)然后調(diào)用RemoteViews內(nèi)部的apply方法加載更新布局.

轉(zhuǎn)載于:https://www.cnblogs.com/wxmdevelop/p/7099745.html

總結(jié)

以上是生活随笔為你收集整理的完全理解Android中的RemoteViews的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。