av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

Android進程通信的方法

在 Android 世界里,默認(rèn)的每個 APP 是一個單獨的進程。其實這樣的描述是不嚴(yán)格的,因為咱們要研究 Android 的進程間通信,肯定出了和其他的 APP 通信外,還可能和同一個 APP 下的其他進程通信,下面為大家詳細(xì)講解一下Android進程通信。

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、重慶小程序開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了山城免費建站歡迎大家使用!

進程間通信(ipc)

IPC方法總是產(chǎn)生客戶/服務(wù)端模式的調(diào)用,也即是客戶端組件(Activity/Service)持有服務(wù)端Service的組件,只能是客戶端主動調(diào)用服務(wù)端的方法,服務(wù)端無法反過來調(diào)用客戶端的方法,因為IPC的另一端Service無法獲取客戶端的對象。

binder

Binder 是一種進程間通信機制。安卓中跨進程通訊就是通過binder。當(dāng)綁定服務(wù)的時候會返回一個binder對象,然后通過他進行多進程間的通信。Binder只需要一次數(shù)據(jù)拷貝,性能上僅次于共享內(nèi)存。

在 Android 系統(tǒng)中,這個運行在內(nèi)核空間,負(fù)責(zé)各個用戶進程通過 Binder 實現(xiàn)通信的內(nèi)核模塊就叫 Binder 驅(qū)動(Binder Dirver)。

Binder IPC 機制中涉及到的內(nèi)存映射通過 mmap() 來實現(xiàn),mmap() 是操作系統(tǒng)中一種內(nèi)存映射的方法。內(nèi)存映射簡單的講就是將用戶空間的一塊內(nèi)存區(qū)域映射到內(nèi)核空間。映射關(guān)系建立后,用戶對這塊內(nèi)存區(qū)域的修改可以直接反應(yīng)到內(nèi)核空間;反之內(nèi)核空間對這段區(qū)域的修改也能直接反應(yīng)到用戶空間。

內(nèi)存映射能減少數(shù)據(jù)拷貝次數(shù),實現(xiàn)用戶空間和內(nèi)核空間的高效互動。兩個空間各自的修改能直接反映在映射的內(nèi)存區(qū)域,從而被對方空間及時感知。也正因為如此,內(nèi)存映射能夠提供對進程間通信的支持。

Binder IPC 正是基于內(nèi)存映射(mmap)來實現(xiàn)的

Binder 通信中的代理模式

我們已經(jīng)解釋清楚 Client、Server 借助 Binder 驅(qū)動完成跨進程通信的實現(xiàn)機制了,但是還有個問題會讓我們困惑。A 進程想要 B 進程中某個對象(object)是如何實現(xiàn)的呢?畢竟它們分屬不同的進程,A 進程 沒法直接使用 B 進程中的 object。

前面我們介紹過跨進程通信的過程都有 Binder 驅(qū)動的參與,因此在數(shù)據(jù)流經(jīng) Binder 驅(qū)動的時候驅(qū)動會對數(shù)據(jù)做一層轉(zhuǎn)換。當(dāng) A 進程想要獲取 B 進程中的 object 時,驅(qū)動并不會真的把 object 返回給 A,而是返回了一個跟 object 看起來一模一樣的代理對象 objectProxy,這個 objectProxy 具有和 object 一摸一樣的方法,但是這些方法并沒有 B 進程中 object 對象那些方法的能力,這些方法只需要把把請求參數(shù)交給驅(qū)動即可。對于 A 進程來說和直接調(diào)用 object 中的方法是一樣的。

當(dāng) Binder 驅(qū)動接收到 A 進程的消息后,發(fā)現(xiàn)這是個 objectProxy 就去查詢自己維護的表單,一查發(fā)現(xiàn)這是 B 進程 object 的代理對象。于是就會去通知 B 進程調(diào)用 object 的方法,并要求 B 進程把返回結(jié)果發(fā)給自己。當(dāng)驅(qū)動拿到 B 進程的返回結(jié)果后就會轉(zhuǎn)發(fā)給 A 進程,一次通信就完成了 其實進程間通信就是為了實現(xiàn)數(shù)據(jù)共享。一個程序不同組件在不同進程也叫多進程,和倆個應(yīng)用沒有本質(zhì)區(qū)別。使用process屬性可以實現(xiàn)多進程,但是會帶來很多麻煩,主要原因是共享數(shù)據(jù)會失敗,弊端有:靜態(tài)和單利失效,同步失效,sharedprefer也變的不可靠等問題。

多進程通信的方式

1.使用intent的附加信息extras來傳遞,通過bundle,傳遞的是bundle支持的類型,比如基本數(shù)據(jù)類型、實現(xiàn)pracellable或serializeable的對象

/**指定包名和帶包名的Activity的名字*/
ComponentName componentName = new ComponentName("com.example.androidaidl", "com.example.androidaidl.MainActivity");
Intent intent = new Intent();
intent.putExtra("id", 1001);
intent.setComponent(componentName);
startActivity(intent);      

2.使用文件共享,序列化或是sharedpre,不過不適用于讀寫并發(fā)的操作 3.廣播:Android的廣播是系統(tǒng)級的,只要傳遞的Action一樣,就可以接收到其他進程廣播的消息,廣播中可以通過Intent傳遞數(shù)據(jù)。 4.scheme協(xié)議是android中的一種頁面內(nèi)跳轉(zhuǎn)協(xié)議,通過定義自己的scheme協(xié)議,可以非常方便跳轉(zhuǎn)app中的各個頁面,并且傳遞數(shù)據(jù),還是可以通過H5頁面跳轉(zhuǎn)指定頁面等。 5.ContentProvider(進程間數(shù)據(jù)共享)和message一樣,底層也是binder,除了oncreate方法其他方法(crud)都是運行在bindler線程里。所以在oncerate里不能做耗時操作。Android本身就提供了不少的ContentProvider訪問,比如聯(lián)系人、相冊等。 訪問ContentProvider,需要通過Uri,需要以“content://”開頭。在其他應(yīng)用訪問通過uri(主機名):

ContentResolver resolver = getActivity().getContentResolver();
/**com.mh.getdata/stock這個要和Provider所在進程中添加的Uri一致*/
Uri uri = Uri.parse("content://com.mh.getdata/stock");
Cursor cursor = resolver.query(uri, null, null, null, null);

常規(guī)通訊

只有允許不同應(yīng)用的客戶端用 IPC 方式訪問服務(wù),并且想要在服務(wù)中處理多線程(多任務(wù))時,才有必要使用 AIDL。 如果您不需要執(zhí)行跨越不同應(yīng)用的并發(fā) IPC,就應(yīng)該通過實現(xiàn)一個 Binder 創(chuàng)建接口;或者,如果您想執(zhí)行 IPC,但根本不需要處理多線程,則使用 Messenger 類來實現(xiàn)接口。無論如何,在實現(xiàn) AIDL 之前,請您務(wù)必理解綁定服務(wù)。 aidl文檔

1.通過 Messenger進行傳遞(handler),在遠程服務(wù)里創(chuàng)建handler(接收客戶端發(fā)送的消息)、 Messenger對像,在onbind里返回( Messenger.getbinder)。在客戶端綁定服務(wù),拿著 Messenger對象發(fā)消息(可以用bundle)。在遠程服務(wù)的handlermessage方法就會收到。他是一個個處理的,如果大量并發(fā)請求用aidl, Messenger底層就是aidl

在客戶端中創(chuàng)建一個Messenger。然后,當(dāng)客戶端收到 onServiceConnected() 回調(diào)時,會向服務(wù)發(fā)送一條 Message,并在其 send() 方法的 replyTo 參數(shù)中包含客戶端的 Messenger。 注意:Messenger和Message是倆個東西

 public void sayHello(View v) {

       if (!mBound) return;
       Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
       try {
          mService.send(msg);
       } catch (RemoteException e) {
           e.printStackTrace();
       }
   }

2.直接使用Binder對象:缺點是這種方式不能進行跨進程,跨應(yīng)用程序的函數(shù)調(diào)用。只能實現(xiàn)在同一個進程之中,同一個應(yīng)用程序之中的不同的組件之間通訊。

用法:繼承Binder,然后在service里return 繼承Binder用它的對象返回,客戶端將bind對象強轉(zhuǎn)成自定義Bind

AIDL

Android interface definition language (android接口定義語言) , 用來跨進程的訪問方法。

aidl操作步驟: 1.在兩個項目中新建普通文件(new ->General->File),后綴名改成(aidl),客戶端和服務(wù)端中這個文件所在的包名要保持一致,內(nèi)容也要一樣 編譯之后, 會在gen目錄下,自動產(chǎn)生同名的,后綴為 Java 的文件。里面有我們要用到的 Stub類。

public static abstract class Stub extends android.os.Binder implements com.example.aidl.AidlFunctions

2.在接口文件AIDLFunctions.aidl中,我們定義一個方法 show

interface AidlFunctions{
   void show();
}

3.AIDL的使用,需要一個Service配合,所以我們在服務(wù)端還要聲明一個Service

public class AIDLService extends Service {
//stub就是系統(tǒng)自動產(chǎn)生的
   AidlFunctions.Stub binder;

   @Override
   public void onCreate() {
       // TODO Auto-generated method stub
       super.onCreate();
   }

   @Override
   public IBinder onBind(Intent intent) {
       // TODO Auto-generated method stub
       binder = new AidlFunctions.Stub() {

           @Override
           //這里是我們在接口中聲明的方法的實現(xiàn)
           public void show() throws RemoteException {
               // TODO Auto-generated method stub
               System.out.println("--------------------收到----------------------");
           }
       };
       return binder;
   }  
}

4.客戶端:

//綁定服務(wù),要用到ServiceConnection
private ServiceConnection serviceConnection;
//自定義的接口,和服務(wù)端一樣
private AidlFunctions aidlFunctions;

serviceConnection = new ServiceConnection() {

   @Override
   public void onServiceDisconnected(ComponentName name) {
       System.out.println("--------------------ServiceDisconnected----------------------");
   }

   @Override
   public void onServiceConnected(ComponentName name, IBinder service) {
       System.out.println("--------------------ServiceConnected----------------------");
       aidlFunctions = AidlFunctions.Stub.asInterface(service);
   }
};
Intent intent = new Intent("com.example.androidaidl.AIDLService");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
//調(diào)用show方法
try {
   aidlFunctions.show();
} catch (RemoteException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
}

使用多進程顯而易見的好處就是分擔(dān)主進程的內(nèi)存壓力。我們的應(yīng)用越做越大,內(nèi)存越來越多,將一些獨立的組件放到不同的進程,它就不占用主進程的內(nèi)存空間了。當(dāng)然還有其他好處,有些應(yīng)用后臺是有多個進程的,啟動一個不可見的輕量級私有進程,在后臺收發(fā)消息,或者做一些耗時的事情,或者開機啟動這個進程,然后做監(jiān)聽等。還有就是防止主進程被殺守護進程,守護進程和主進程之間相互監(jiān)視,有一方被殺就重新啟動它。因為它們要常駐后臺,特別是即時通訊或者社交應(yīng)用。


文章標(biāo)題:Android進程通信的方法
路徑分享:http://uogjgqi.cn/article/djsohpc.html
掃二維碼與項目經(jīng)理溝通

我們在微信上24小時期待你的聲音

解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流