<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 功能強大 支持多語言、二開方便! 廣告
                總結上面所描述的數據更新通知機制的流程如圖8-2所示。 :-: ![](http://img.blog.csdn.net/20150803131352144?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖8-2 數據更新通知的流程圖 從前面的代碼介紹和圖8-2所示的流程來看,Android平臺中的數據更新通知機制還較為簡單。不過此處尚有幾個問題想和讀者一起探討。 問題一:由圖8-2可知,客戶端2調用ContentProvider的update函數將間接觸發客戶端1的ContentObserver的onChange函數被調用。如果客戶端1在onChange函數中耗時過長,會不會導致客戶端2阻塞在update函數中呢? 想到這個問題的讀者應該是非常細致和認真的了。確實,從前面所示的代碼和流程圖來看,這個情況幾乎是必然會發生的,但是實際上該問題并不存在,原因在于下面這一段代碼: **IContentObserver.java::Proxy:onChange** ~~~ private static class Proxy implementsandroid.database.IContentObserver { privateandroid.os.IBinder mRemote; ...... publicvoid onChange(boolean selfUpdate) throws android.os.RemoteException { android.os.Parcel_data = android.os.Parcel.obtain(); try{ _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(((selfUpdate)? (1) : (0))); //調用客戶端1的ContentObserver Bn端的onChange函數 mRemote.transact(Stub.TRANSACTION_onChange,_data, null, android.os.IBinder.FLAG_ONEWAY); } finally { _data.recycle(); } } ...... } ~~~ 以上代碼告訴我們,ContentService在調用客戶端注冊的IContentObserver 的onChange函數時,使用了FLAG_ONEWAY標志。根據第2章對該標志的介紹(參見2.2.1節),使用該標志的Binder調用只需將請求發給binder驅動即可,無需等待客戶端onChange函數的返回。因此,即使客戶端1在onChange中惡意浪費時間,也不會阻塞客戶端2的update函數了。 問題二:這是一個開放性問題,最終需要讀者給出合適的答案。 假設服務端有一項功能,需要客戶端通過某種方式來控制它的開閉(即禁止或使用該功能),考慮一下有幾種方式來實現這個控制機制。 Android平臺上至少有三種方法可以實現這個控制機制。 - 第一種:服務端實現一個API函數,客戶端直接調用這個函數來控制。 - 第二種客戶端發送指定的廣播,而服務端注冊該廣播的接收者,然后在這個廣播接收者的onReceive函數中去處理。 - 第三種:服務端輸出一個ContentProvider,并為這個功能輸出一個uri地址,然后注冊一個ContentObserver。客戶端可通過更新數據的方式來觸發服務端ContentObserver的onChange函數,服務端在該函數中做對應處理即可。 在Android代碼中,這三種方法都有地方使用。下面將以Settings應用中和USB相關的功能設置為例來觀察第一種和第三種方法的使用情況。 第一個實例和Android 4.0中新支持的USB MTP/PTP功能有關,相關代碼如下: **UsbSettings.java::onPreferenceTreeClick** ~~~ public booleanonPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { ...... if(preference == mMtp) { mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP,true); updateToggles(UsbManager.USB_FUNCTION_MTP); } else if(preference == mPtp) { mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP, true); updateToggles(UsbManager.USB_FUNCTION_PTP); } returntrue; } ~~~ 由以上代碼可知,如果用戶從Settings界面中選擇了使能MTP,將直接調用UsbManager的setCurrentFunction來使能MTP功能。這個函數的Bn端實現在UsbService中。 不過,同樣是USB相關的功能控制,ADB的開關控制卻采用了第三種方法,相關代碼為: **DevelopmentSettings.java::onClick** ~~~ public void onClick(DialogInterface dialog, intwhich) { if (which == DialogInterface.BUTTON_POSITIVE){ mOkClicked = true; //設置Settings數據庫ADB對應的數據項值為1 Settings.Secure.putInt(getActivity().getContentResolver(), Settings.Secure.ADB_ENABLED, 1); } else mEnableAdb.setChecked(false);//界面更新 } ~~~ 上面的數據項更新操作將導致UsbDeviceManager做對應處理,其相關代碼如下: **UsbDeviceManager.java::onChange** ~~~ private class AdbSettingsObserver extendsContentObserver { ...... publicvoid onChange(boolean selfChange) { //從數據庫中取出對應項的值 boolean enable =(Settings.Secure.getInt(mContentResolver, Settings.Secure.ADB_ENABLED, 0) > 0); //發送MSG_ENABLE_ADB消息,UsbDeviceManager將處理此消息 mHandler.sendMessage(MSG_ENABLE_ADB, enable); } } ~~~ 同樣是USB相關的功能,Settings應用卻采用了兩種截然不同的方法來處理它們。這種做法為筆者目前所從事的項目中USB擴展功能的實現帶來了極大困擾,因為我們想采用統一的方法來處理USB相關功能。到底應采用哪種方法比較合適呢?第一種方法和第三種方法各自的適用場景是什么?讀者不妨仔細思考并將結論告訴筆者。 問題三:我們在第7章中分析Cursorquery時曾看到過ContentObserver的身影,但是并沒有對其進行詳細分它。如果現在回過頭去分析query流程中和ContentObserver相關的部分,所涉及的流程可能比本節內容還要多。
                  <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>

                              哎呀哎呀视频在线观看