close

@ What is Widget
AppWidget framework通過broadcast intents和你的widget溝通,例如當需要更新Widget的時候。透過使用RemoteViews構建和發送。RemoteViews將Widget的layout和特定内容包裝後,藉由IPC傳送到Launcher,最後顯示到桌面上。

@ What is RemoteViews
RemoteViews並不是一個真正的View,而只是一個用於整合Widget裡layout呈現與view元件行為的一個Wrapper class(也就是appWidget所要長得樣子),透過RemoteView把建立該Widget需要的resource ID和各個元件的事件封裝起來。 RemoteViews會通過進程間通信機制傳遞給AppWidgetHost。
 
@為什麼要有RomoteView
因為activity跟widget的運作機制的不同,應用程式AP裡的Avtivity要更新元件時,可以直接取得該元件進行更新。而因為Widget架構是繼承appWidgetProvider,所以每個widget就是一個BroadcastReceiver。
 
在Widget裡並無法直接對於元件進行更新,因為Widget實際畫面是在Launcher AppWidgetHostView上呈現,故實際對於Widget元件的操作都在AppWidgetHostView進行,所以需要藉由RemoteView,主要目的在把Widget的所有元件進行封裝,透過RemoteView告訴Launcher你想要的AppWidget是長什麼樣子又因為Widget跟Launcher處在不同的process,所以運作過程如下:
 
1. 透過AppWidgetManger傳送要更新AppWidget的識別id以及更新內容(remoteview)。
2. 在AppWidgetManger通知AppWidgetService哪些AppWidgetId需要更新View。
3. 透過aidl IPC機制,將widgetID跟RemoteView傳遞給AppWidgetHost。
4. AppWidgetHost會根據WidgetId找出放置該Widget的AppWidgetHostView,接著把RemoteView傳送過去。
5. 在AppWidgetHostView的updateAppWidget主要任務為:

(1)第一次:會建立Widget的畫面與資料
會呼叫RemoteView.apply() : 執行LayoutInflater.inflate()將xml轉成view,並且抓出RemoteView裡的元件,處理相對應的method,
如updateViews.setTextViewText(),則會去執行TextView的setTextViewText()
-->接著設定Widget的LayoutParams,也就是呈現在畫面上的大小跟位置
-->最後把remoteView加到ViewGroup裡。
 

(2)第二次:更新Widget資訊
-->呼叫RemoteView的reapply(context,view)
-->處理RemoteView元件裡相對應的method。
 
public final AppWidgetHostView createView(Context context, int appWidgetId,
          AppWidgetProviderInfo appWidget) {

    AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
    view.setAppWidget(appWidgetId, appWidget);
    synchronized (mViews) {
        mViews.put(appWidgetId, view);
    }

    RemoteViews views;
    try {
        views = sService.getAppWidgetViews(appWidgetId);
    } catch (RemoteException e) {
        throw new RuntimeException("system server dead?", e);
    }
    view.updateAppWidget(views);
    return view;
}
 
 
當Widget接收到廣播需要update時,會透過appWidgetManager呼叫appWidgetService,然後利用aidl的機制將訊息傳給Home,通知Launcher需作更新UI的動作。
 
而在devices上看到的Widget畫面實際上是Launcher裡的AppWidgetHostView。為了更新Launcher上widget的狀態,當Widget要更新畫面時,需要傳送描述動作(remoteview),讓home的hostview顯示出來。Android default widget使用remoteview將此widget所需要的icon, title等描述成action, 並傳遞action array至home的appWidgetHostView最後由Home的appWidgetHostView將remoteview呈現出來。
 
@RemoteView與Widget的關聯性
RemoteView就像個View的集合,描述要呈現在Launcher上的widget component。
 
@Widget是個process,怎麼與Home溝通
當Widget接收到廣播需要update時,會透過appWidgetManager呼叫appWidgetService,然後利用aidl的機制將訊息傳給Home,通知Launcher需作更新UI的動作。
 
@為什麼AP不這樣作
AP是Activity,可以直接操作component更新,所以不需要RemoteView。Widget是Broadcastreceiver,且真正呈現Widget是在Launcher裡的AppWidgetHostView,所以需要透過RemoteView將要呈現Widget裡的component透過RemoteView包裝起來,並藉由IPC的機制,傳送到Launcher裡,最後秀出畫面。
arrow
arrow
    全站熱搜

    cloudfly 發表在 痞客邦 留言(0) 人氣()