日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

由于Android系統中應用程序之間不能共享內存。因此,在不同應用程序之間交互數據(跨進程通訊)就稍微麻煩一些。

進程間通信(ipc)

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

binder

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

在 Android 系統中,這個運行在內核空間,負責各個用戶進程通過 Binder 實現通信的內核模塊就叫 Binder 驅動(Binder Dirver)。

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

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

Binder IPC 正是基于內存映射(mmap)來實現的

Binder 通信中的代理模式

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

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

當 Binder 驅動接收到 A 進程的消息后,發現這是個 objectProxy 就去查詢自己維護的表單,一查發現這是 B 進程 object 的代理對象。于是就會去通知 B 進程調用 object 的方法,并要求 B 進程把返回結果發給自己。當驅動拿到 B 進程的返回結果后就會轉發給 A 進程,一次通信就完成了

其實進程間通信就是為了實現數據共享。一個程序不同組件在不同進程也叫多進程,和倆個應用沒有本質區別。使用process屬性可以實現多進程,但是會帶來很多麻煩,主要原因是共享數據會失敗,弊端有:靜態和單利失效,同步失效,sharedprefer也變的不可靠等問題。

多進程通信的方式

1.使用intent的附加信息extras來傳遞,通過bundle,傳遞的是bundle支持的類型,比如基本數據類型、實現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,不過不適用于讀寫并發的操作

3.廣播:Android的廣播是系統級的,只要傳遞的Action一樣,就可以接收到其他進程廣播的消息,廣播中可以通過Intent傳遞數據。

4.scheme協議是android中的一種頁面內跳轉協議,通過定義自己的scheme協議,可以非常方便跳轉App中的各個頁面,并且傳遞數據,還是可以通過H5頁面跳轉指定頁面等。

5.ContentProvider(進程間數據共享)和message一樣,底層也是binder,除了oncreate方法其他方法(crud)都是運行在bindler線程里。所以在oncerate里不能做耗時操作。Android本身就提供了不少的ContentProvider訪問,比如聯系人、相冊等。 訪問ContentProvider,需要通過Uri,需要以“content://”開頭。在其他應用訪問通過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);

常規通訊

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

aidl文檔

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

在客戶端中創建一個Messenger。然后,當客戶端收到 onServiceConnected() 回調時,會向服務發送一條 Message,并在其 send() 方法的 replyTo 參數中包含客戶端的 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對象:缺點是這種方式不能進行跨進程,跨應用程序的函數調用。只能實現在同一個進程之中,同一個應用程序之中的不同的組件之間通訊。

用法:繼承Binder,然后在service里return

繼承Binder用它的對象返回,客戶端將bind對象強轉成自定義Bind

AIDL

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

aidl操作步驟:

1.在兩個項目中新建普通文件(new ->General->File),后綴名改成(aidl),客戶端和服務端中這個文件所在的包名要保持一致,內容也要一樣

編譯之后, 會在gen目錄下,自動產生同名的,后綴為 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配合,所以我們在服務端還要聲明一個Service

public class AIDLService extends Service {

//stub就是系統自動產生的

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

//這里是我們在接口中聲明的方法的實現

public void show() throws RemoteException {

// TODO Auto-generated method stub

System.out.println("--------------------收到----------------------");

}

};

return binder;

}

}

4.客戶端:

//綁定服務,要用到ServiceConnection

private ServiceConnection serviceConnection;

//自定義的接口,和服務端一樣

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);

//調用show方法

try {

aidlFunctions.show();

} catch (RemoteException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

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

linux就該這么學pdf版下載地址:https://www.linuxprobe.com/book

分享到:
標簽:進程 Android
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定