android中的widget是非常有意思的一個功能夭谤,widget不是運(yùn)行在自己的進(jìn)程中棺牧,通常是運(yùn)行在桌面、鎖屏等應(yīng)用上朗儒,如何理解跨進(jìn)程通信并更新widget界面颊乘,是理解widget的關(guān)鍵参淹。
widget核心是一個廣播接收器,AppWidgetProvider乏悄,它有幾個核心的回調(diào)函數(shù)承二。
// 沒接收一次廣播消息就調(diào)用一次,使用頻繁
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
// 每次更新都調(diào)用一次該方法纲爸,使用頻繁
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
// 沒刪除一個就調(diào)用一次
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}
// 當(dāng)該Widget第一次添加到桌面是調(diào)用該方法,可添加多次但只第一次調(diào)用
public void onEnabled(Context context) {
super.onEnabled(context);
}
// 當(dāng)最后一個該Widget刪除是調(diào)用該方法妆够,注意是最后一個
public void onDisabled(Context context) {
super.onDisabled(context);
}
根據(jù)實(shí)際需要识啦,監(jiān)聽對應(yīng)事件,實(shí)現(xiàn)相應(yīng)的方法神妹,在相應(yīng)接口中更新widget界面颓哮。
widget必須在androidmenifest.xml文件中配置插件信息,以便包管理服務(wù)識別鸵荠。
<receiver
android:label="@string/app_name_timewidget"
android:name="com.owl.mythou.TimeWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/time_widget_config">
</meta-data>
</receiver>
widget的初始配置文件如下冕茅,需要指定插件的最小寬高以及其它可選項(xiàng),刷新頻率蛹找,默認(rèn)效果圖片等等姨伤。
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/time_widget_layout"
android:minWidth="286dip"
android:minHeight="142dip"
android:updatePeriodMillis="0">
</appwidget-provider>
- android:initialLayout 指定界面布局的Layout文件,和activity的Layout一樣
- android:minWidth 你的widget的最小寬度庸疾。根據(jù)Layout的單元格計算(72*格子數(shù)-2)
- android:minHeigh 你的widget的最小高度乍楚。計算方式和minwidth一樣。
- android:updatePerioMillis 使用系統(tǒng)定時更新服務(wù)届慈,單位毫秒徒溪。
widget的具體開發(fā)如上,但到底是如何影響到桌面顯示金顿,它們的包名不一樣臊泌,進(jìn)程也不一樣。它們是如何進(jìn)行跨進(jìn)程通信揍拆。在理解widget之前渠概,必須要理解android中的remoteviews是如何工作的。
remoteviews礁凡,顧名思義是遠(yuǎn)程view高氮,但它不是一個真正的view,因?yàn)檎嬲膙iew是無法跨進(jìn)程通信的顷牌,remoteviews實(shí)現(xiàn)了parcelable接口剪芍,可以實(shí)現(xiàn)跨進(jìn)程通信,可以將remoteviews理解為一個view的描述文件窟蓝,其內(nèi)部維護(hù)了一個action列表罪裹,每個action記錄了用戶調(diào)用的方法名饱普,參數(shù),最終實(shí)現(xiàn)反射調(diào)用状共,實(shí)現(xiàn)用戶設(shè)置的ui效果套耕。
widget應(yīng)用維護(hù)著一個remoteviews,當(dāng)widget需要更新時峡继,必須通過widget服務(wù)刷新冯袍,以便通知桌面或鎖屏實(shí)現(xiàn)界面更新。
邏輯調(diào)用時序圖如上所示碾牌。AppWidgetHost有一個實(shí)現(xiàn)了IAppWidgetHost的callback內(nèi)部對象康愤,這樣能就通過aidl方式實(shí)現(xiàn)跨進(jìn)程通信了。具體調(diào)用如上舶吗,widget服務(wù)跨進(jìn)程調(diào)用到widgethost當(dāng)中征冷,完成widgethostview的更新,這樣桌面就實(shí)現(xiàn)了界面刷新誓琼。因?yàn)樽烂嬖诔跏蓟臅r候會將widgethostview添加到界面上检激。
widget機(jī)制,歡迎交流補(bǔ)充腹侣。