RemoteView

來源:http://www.reibang.com/p/fc237e90cd5f(吹爆)

介紹

遠(yuǎn)程View捞镰,它表示的是一個View結(jié)構(gòu),它可以在其他進(jìn)程中顯示毙替,為了跨進(jìn)程更新它的界面岸售,RemoteViews提供了一組基礎(chǔ)的操作來實現(xiàn)這個效果。

RemoteViews在Android中的使用場景有兩種:

  • 通知欄
  • 桌面小部件

桌面小部件

  1. 定義小部件布局
  2. 定義小部件配置信息< appwidget-provider
屬性 含義
android:initialLayout 指定小部件的初始化布局
android:minHeight 小部件最小高度
android:minWidth 小部件最小寬度
android:previewImage 小部件列表顯示的圖標(biāo)
android:updatePeriodMillis 小部件自動更新的周期
android:widgetCategory 小部件顯示的位置厂画,home_screen表示只在桌面上顯示
  1. 定義小部件的實現(xiàn)類,extends AppWidgetProvider
  2. 清單文件聲明
<receiver android:name=".CustomAppWidgetProvider">
    <meta-data
        android:name="android.appwidget.provider" // name固定
        android:resource="@xml/app_widget_provider_info" /> // xml

    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> // 必須加的凸丸,它作為小部件的標(biāo)識存在
        <action android:name="com.shenhuniurou.appwidgetprovider.click.one" /> // 其他action對應(yīng)點擊動作
        <action android:name="com.shenhuniurou.appwidgetprovider.click.two" />
        <action android:name="com.shenhuniurou.appwidgetprovider.click.three" />
        <action android:name="com.shenhuniurou.appwidgetprovider.click.four" />
    </intent-filter>
</receiver>

總結(jié):

  1. 當(dāng)小部件一被添加到桌面時會調(diào)用Provider中的onUpdate方法,在這個方法中我們會通過AppWidgetManager去更新小部件的界面
  2. 通過RemoteViews來操作木羹,setOnClickPendingIntent給每個按鈕設(shè)置了點擊時會發(fā)送的廣播動作甲雅,而在清單文件中我們聲明小部件時已經(jīng)將這些廣播動作都加到intent-filter解孙,所以當(dāng)我們點擊桌面上該小部件中的某個按鈕時,就會發(fā)送對應(yīng)的廣播抛人,而小部件監(jiān)聽了這個廣播弛姜,接收到廣播后再onReceive方法中根據(jù)動作來分別處理點擊事件。
  3. 對小部件的一些其他操作方法(比如onEnabled妖枚、onDisabled廷臼、onDeleted)的廣播也會在onReceive中接收到,然后分發(fā)給不同的方法绝页。

PendingIntent

將要發(fā)生的意圖荠商,和Intent的區(qū)別就在于一個是立即執(zhí)行的一個是在未來某個時候執(zhí)行。(通知中點擊通知時跳轉(zhuǎn)頁面)

給RemoteViews設(shè)置點擊事件续誉,就必須使用PendingIntent懊渡,通過setOnClickPendingIntent方法來設(shè)置涕蜂。
PendingIntent是通過send和cancel方法來發(fā)送和取消待執(zhí)行的Intent专酗。

PendingIntent支持三種待定意圖:

  1. 啟動activity(常見的通知)
    啟動Activity它有兩種滥比,啟動單個和啟動多個,當(dāng)使用getActivities時臼隔,實際上啟動的是Intent數(shù)組中最后一個activity嘹裂,如果要讓最后一個activity返回時不退出app而是退回到上一個activity,實現(xiàn)方式可參照我上面第一個按鈕的點擊處理摔握。

  2. 啟動Service

  3. 發(fā)送廣播

PendingIntent 方法參數(shù)

getActivity寄狼、getService、getBroadcast這三個方法的參數(shù)意義都是相同的氨淌,第一個上下文泊愧,第三個待定的意圖,第二個requestCode表示PendingIntent發(fā)送方的請求碼盛正,多數(shù)情況下設(shè)置為0即可拼卵,另外requestCode會影響到第四個參數(shù)flags的效果。flags這個標(biāo)志位表示執(zhí)行效果蛮艰。

PendingIntent的匹配規(guī)則
如果兩個PendingIntent它們內(nèi)部的Intent相同,且requestCode也相同雀彼,那么這兩個PendingIntent就是相同的壤蚜;
Intent相同的情況
如果兩個Intent的ComponentName和intent-filter都相同,那么這兩個Intent就是相同的
(Extras不參與Intent的匹配過程徊哑,就是它不同袜刷,只要ComponentName和intent-filter相同,Intent都算相同的莺丑。)

flags 執(zhí)行效果

FLAG_ONE_SHOT:表示當(dāng)前描述的PendingIntent只能被使用一次著蟹,然后它就會自動cancel墩蔓,如果后續(xù)還有相同的PendingIntent,那么它們的send方法就會調(diào)用失敗萧豆。如果通知欄消息使用這種標(biāo)記位奸披,同類型的通知就只會被打開一次,后續(xù)的通知將無法點開涮雷。

FLAG_NO_CREATE:表示當(dāng)前描述的PendingIntent不會主動創(chuàng)建阵面,如果當(dāng)前PendingIntent之前不存在,那么getActivities等這些方法會直接返回null洪鸭,獲取PendingIntent失敗样刷。它無法單獨使用。

FLAG_CANCEL_CURRENT:表示當(dāng)前描述的PendingIntent如果已經(jīng)存在览爵,就cancel它置鼻,然后系統(tǒng)會創(chuàng)建一個新的。

FLAG_UPDATE_CURRENT:表示當(dāng)前描述的PendingIntent如果已經(jīng)存在蜓竹,那么它會被更新箕母,內(nèi)部的Intent中的Extras也會被更新。

RemoteViews的內(nèi)部機(jī)制

通知欄和桌面小部件分別由NotificationManager和AppWidgetManager來管理的梅肤,而NotificationManager和AppWidgetManager是通過Binder分別和SystemServer進(jìn)程中的NotificationManagerService以及AppWidgetService進(jìn)行通信司蔬。
因此,通知欄和桌面小部件中的布局文件實際上是在NotificationManagerService和AppWidgetService中被加載的姨蝴,而他們運行在SystemServer中俊啼,這其實已經(jīng)和我們自己的app進(jìn)程構(gòu)成了跨進(jìn)程通信。

理論分析

  1. 首先RemoteViews會通過Binder傳遞到SystemServer進(jìn)程
    (因為RemoteViews實現(xiàn)了Parcelable接口左医,可以跨進(jìn)程傳輸)
  2. 系統(tǒng)會根據(jù)RemoteViews中的包名等信息去獲取到該app的資源
  3. 然后通過LayoutInflater去加載RemoteViews中的布局文件授帕。
    在SystemServer進(jìn)程中加載后的布局文件是一個普通的View,只不過對于我們的app進(jìn)程來說浮梢,它是一個遠(yuǎn)程View也就是RemoteViews跛十。
  4. 接著系統(tǒng)會對View執(zhí)行一系列界面更新任務(wù)
    這些任務(wù)就是之前我們通過set方法提交的,set方法對View的更新操作并不是立刻執(zhí)行的
    在RemoteViews內(nèi)部會記錄所有的更新操作秕硝,具體的執(zhí)行要等到RemoteViews被完全加載以后芥映,這樣RemoteViews就可以在SystemServer中進(jìn)程中顯示了,這就是我們所看到的通知欄消息和桌面小部件远豺。
    當(dāng)需要更新RemoteViews時奈偏,我們又需要調(diào)用一系列set方法通過NotificationManager和AppWidgetManager來提交更新任務(wù),具體更新操作也是在SystemServer進(jìn)程中完成的躯护。

理論上講系統(tǒng)完全可以通過Binder去支持所有的View和View操作惊来,但是這樣做代價太大,View的方法太多了棺滞,另外大量的IPC操作會影響效率裁蚁。

為了解決這個問題矢渊,系統(tǒng)并沒有通過Binder去直接支持View的跨進(jìn)程訪問,而是提供了一個Action的概念枉证。

Action代表一個View操作矮男,Action同樣實現(xiàn)了Parcelable接口。系統(tǒng)首先將View操作封裝到Action對象并將這些對象跨進(jìn)程傳輸?shù)竭h(yuǎn)程進(jìn)程刽严,接著在遠(yuǎn)程進(jìn)程中執(zhí)行Action對象中的具體操作昂灵。

在我們的app中每調(diào)用一次set方法,RemoteViews中就會添加一個對應(yīng)的Action對象舞萄,當(dāng)我們通過NotificationManager和AppWidgetManager來提交我們的更新時眨补,這些Action對象就會傳輸?shù)竭h(yuǎn)程進(jìn)程并在遠(yuǎn)程進(jìn)程中依次執(zhí)行。

遠(yuǎn)程進(jìn)程通過RemoteViews的apply方法來進(jìn)行View的更新操作倒脓,apply方法內(nèi)部是去遍歷所有的Action對象并調(diào)用它們的apply方法撑螺,具體的View更新操作是由Action對象的apply方法來完成。

好處

  1. 不需要定義大量的Binder接口
  2. 通過在遠(yuǎn)程進(jìn)程中批量執(zhí)行RemoteViews的更新操作從而避免了大量的IPC操作崎弃,這就提高了程序的性能甘晤。

RemoteViews的優(yōu)缺點

優(yōu)點:實際開發(fā)中,跨進(jìn)程通信我們可以選擇AIDL去實現(xiàn)饲做,但是如果對界面的更新比較頻繁线婚,這時會有效率問題,而且AIDL接口可能會變得很復(fù)雜盆均,但如果采用RemoteViews來實現(xiàn)就沒有這個問題了

缺點:僅支持一些常見的View塞弊,而對于自定義View是不支持的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泪姨,一起剝皮案震驚了整個濱河市游沿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肮砾,老刑警劉巖诀黍,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仗处,居然都是意外死亡眯勾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門婆誓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咒精,“玉大人,你說我怎么就攤上這事旷档。” “怎么了歇拆?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵鞋屈,是天一觀的道長范咨。 經(jīng)常有香客問我,道長厂庇,這世上最難降的妖魔是什么渠啊? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮权旷,結(jié)果婚禮上替蛉,老公的妹妹穿的比我還像新娘。我一直安慰自己拄氯,他們只是感情好躲查,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著译柏,像睡著了一般镣煮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鄙麦,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天典唇,我揣著相機(jī)與錄音,去河邊找鬼胯府。 笑死介衔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骂因。 我是一名探鬼主播炎咖,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼侣签!你這毒婦竟也來了塘装?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤影所,失蹤者是張志新(化名)和其女友劉穎蹦肴,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猴娩,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡阴幌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卷中。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矛双。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蟆豫,靈堂內(nèi)的尸體忽然破棺而出议忽,到底是詐尸還是另有隱情,我是刑警寧澤十减,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布栈幸,位于F島的核電站愤估,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏速址。R本人自食惡果不足惜玩焰,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芍锚。 院中可真熱鬧昔园,春花似錦、人聲如沸并炮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渣触。三九已至羡棵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嗅钻,已是汗流浹背皂冰。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留养篓,地道東北人秃流。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像柳弄,于是被迫代替她去往敵國和親舶胀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359