<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ### 5.3 RemoteViews的意義 在5.2節中我們分析了RemoteViews的內部機制,了解RemoteViews的內部機制可以讓我們更加清楚通知欄和桌面小工具的底層實現原理,但是本章對RemoteViews的探索并沒有停止,在本節中,我們將打造一個模擬的通知欄效果并實現跨進程的UI更新。 首先有2個Activity分別運行在不同的進程中,一個名字叫A,另一個叫B,其中A扮演著模擬通知欄的角色,而B則可以不停地發送通知欄消息,當然這是模擬的消息。為了模擬通知欄的效果,我們修改A的process屬性使其運行在單獨的進程中,這樣A和B就構成了多進程通信的情形。我們在B中創建RemoteViews對象,然后通知A顯示這個RemoteViews對象。如何通知A顯示B中的RemoteViews呢?我們可以像系統一樣采用Binder來實現,但是這里為了簡單起見就采用了廣播。B每發送一次模擬通知,就會發送一個特定的廣播,然后A接收到廣播后就開始顯示B中定義的RemoteViews對象,這個過程和系統的通知欄消息的顯示過程幾乎一致,或者說這里就是復制了通知欄的顯示過程而已。 首先看B的實現,B只要構造RemoteViews對象并將其傳輸給A即可,這一過程通知欄是采用Binder實現的,但是本例中采用廣播來實現,RemoteViews對象通過Intent傳輸到A中,代碼如下所示。 RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout. layout_simulated_notification); remoteViews.setTextViewText(R.id.msg, "msg from process:" + Process. myPid()); remoteViews.setImageViewResource(R.id.icon, R.drawable.icon1); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, DemoActivity_1.class), PendingIntent.FLAG_ UPDATE_CURRENT); PendingIntent openActivity2PendingIntent = PendingIntent.getActivity( this, 0, new Intent(this, DemoActivity_2.class), PendingIntent. FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.item_holder, pendingIntent); remoteViews.setOnClickPendingIntent(R.id.open_activity2, openActivity2- PendingIntent); Intent intent = new Intent(MyConstants.REMOTE_ACTION); intent.putExtra(MyConstants.EXTRA_REMOTE_VIEWS, remoteViews); sendBroadcast(intent); A的代碼也很簡單,只需要接收B中的廣播并顯示RemoteViews即可,如下所示。 public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private LinearLayout mRemoteViewsContent; private BroadcastReceiver mRemoteViewsReceiver=new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { RemoteViews remoteViews = intent.getParcelableExtra(MyConstants. EXTRA_REMOTE_VIEWS); if (remoteViews ! = null) { updateUI(remoteViews); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { mRemoteViewsContent = (LinearLayout) findViewById(R.id.remote_ views_content); IntentFilter filter = new IntentFilter(MyConstants.REMOTE_ACTION); registerReceiver(mRemoteViewsReceiver, filter); } private void updateUI(RemoteViews remoteViews) { View view = remoteViews.apply(this, mRemoteViewsContent); mRemoteViewsContent.addView(view); } @Override protected void onDestroy() { unregisterReceiver(mRemoteViewsReceiver); super.onDestroy(); } } 上述代碼很簡單,除了注冊和解除廣播以外,最主要的邏輯其實就是updateUI方法。當A收到廣播后,會從Intent中取出RemoteViews對象,然后通過它的apply方法加載布局文件并執行更新操作,最后將得到的View添加到A的布局中即可。可以發現,這個過程很簡單,但是通知欄的底層就是這么實現的。 本節這個例子是可以在實際中使用的,比如現在有兩個應用,一個應用需要能夠更新另一個應用中的某個界面,這個時候我們當然可以選擇AIDL去實現,但是如果對界面的更新比較頻繁,這個時候就會有效率問題,同時AIDL接口就有可能會變得很復雜。這個時候如果采用RemoteViews來實現就沒有這個問題了,當然RemoteViews也有缺點,那就是它僅支持一些常見的View,對于自定義View它是不支持的。面對這種問題,到底是采用AIDL還是采用RemoteViews,這個要看具體情況,如果界面中的View都是一些簡單的且被RemoteViews支持的View,那么可以考慮采用RemoteViews,否則就不適合用RemoteViews了。 如果打算采用RemoteViews來實現兩個應用之間的界面更新,那么這里還有一個問題,那就是布局文件的加載問題。在上面的代碼中,我們直接通過RemoteViews的apply方法來加載并更新界面,如下所示。 View view = remoteViews.apply(this, mRemoteViewsContent); mRemoteViewsContent.addView(view); 這種寫法在同一個應用的多進程情形下是適用的,但是如果A和B屬于不同應用,那么B中的布局文件的資源id傳輸到A中以后很有可能是無效的,因為A中的這個布局文件的資源id不可能剛好和B中的資源id一樣,面對這種情況,我們就要適當修改RemoteViews的顯示過程的代碼了。這里給出一種方法,既然資源id不相同,那我們就通過資源名稱來加載布局文件。首先兩個應用要提前約定好RemoteViews中的布局文件的資源名稱,比如“layout_simulated_notification”,然后在A中根據名稱查找到對應的布局文件并加載,接著再調用RemoteViews的reapply方法即可將B中對View所做的一系列更新操作全部作用到A中加載的View上面。關于apply和reapply方法的差別在前面已經提到過,這里就不多說了,這樣整個跨應用更新界面的流程就走通了,具體效果如圖5-4所示。可以發現B中的布局文件已經成功地在A中顯示了出來。修改后的代碼如下: :-: ![](https://img.kancloud.cn/a3/03/a303d8e9a67c04f9bf528ac412feb6b6_875x608.png) 圖5-4 模擬通知欄的效果 int layoutId = getResources().getIdentifier("layout_simulated_ notification", "layout", getPackageName()); View view = getLayoutInflater().inflate(layoutId, mRemoteViewsContent, false); remoteViews.reapply(this, view); mRemoteViewsContent.addView(view);
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看