国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

IPC機制(一)

2019-11-06 09:35:38
字體:
供稿:網(wǎng)友

一、概念

ipC:inter-PRocess Communication,進程間通信或者跨進程通信。例如:Bundle、文件共享、基于Binder的AIDL和Messenger、ContentProvider、Socket等1、線程:CPU調(diào)度的最小單位進程:一個執(zhí)行單元,一般指一個程序或應(yīng)用。一個進程可包含多個線程。2、應(yīng)用場景:一個應(yīng)用采用多線程,兩個應(yīng)用間通信。3、開始多進程(1)給四大組件在清單文件中指定Android:process屬性,開啟多進程。 默認進程的進程名是包名。 系統(tǒng)為每個應(yīng)用分配一個唯一UID,UID相同的應(yīng)用才能共享數(shù)據(jù)。 (擁有獨立虛擬機,application,內(nèi)存空間)(2)通過JNI在native層fork一個新的進程通過adb shell ps | grep 包名 查看一個包名下所存在的進程信息4、多進程的問題:每個進程分配獨立的虛擬機,不同虛擬機在內(nèi)存分配上有不同地址空間,所以在訪問同一個類對象產(chǎn)生多個副本。如果多進程之間通過內(nèi)存同享數(shù)據(jù)會同享失敗。(1)靜態(tài)成員和單例模式失效(2)線程同步機制失效 (不在同一內(nèi)存,無法鎖住同一對象)(3)SharedPreferences可靠性下降(sp不支持兩個進程同時執(zhí)行寫操作)(4)Application多次創(chuàng)建(同一進程、同一虛擬機、同一Application)5、Android中的IPC方式:(1)、使用Bundle :Activity、Service和Receive都支持Intent中傳遞Bundle數(shù)據(jù),由于Bundle實現(xiàn)了Parcelable接口,可在不同進程中進行通信。(2)、使用文件共享(但是兩個線程同時操作可能會出問題,sharedPrefrences有緩存策略,讀寫不可靠)(3)、使用Messenger : 不同進程中傳遞Message對象,底層實現(xiàn)是AIDL(4)、使用AIDL:(5)、使用ContentProvider: 不同應(yīng)用中進行數(shù)據(jù)共享,底層實現(xiàn)是Binder(6)、Socket:通過網(wǎng)絡(luò)傳輸字實現(xiàn)實時通信Messenger和AIDL區(qū)別:Messenger以串行方式處理消息,如果有大量的并發(fā)請求,只能一個個處理,不適合使用Messenger。AIDL可以跨進程調(diào)用方法,Messenger只能傳遞消息二、序列化序列化,表示將一個對象轉(zhuǎn)換成可存儲或可傳輸?shù)臓顟B(tài)。序列化后的對象可以在網(wǎng)絡(luò)上進行傳輸,也可以存儲到本地。通過Intent和Binder傳輸數(shù)據(jù)時需要使用序列化(內(nèi)存和內(nèi)存之間傳輸?shù)臄?shù)據(jù)需要序列化以后的行式) 1、Serializable接口:序列化接口聲明一個serialVersionUID。在反序列過程中,會對兩個UID進行對比,如果一致才可以進行反序列化。如果不聲明UID,在反序列時,當前類發(fā)生改變(增加或刪除了變量),會反序列化失敗。注:靜態(tài)成員變量屬于類,不會對象,不會參與序列化。用transient關(guān)鍵字標記的變量不參與序列化。原理:將一個對象轉(zhuǎn)換成可存儲可傳輸?shù)臓顟B(tài)。 2、Parcelable接口:實現(xiàn)這個接口,可以通過Intent和Binder進行傳遞。實現(xiàn)Parceable接口,重寫describeContents和writeToPracel()兩個方法。還需要提供一個CREATOR的常量,重寫createFromParcel()和newArray()兩個方法。 原理: 將一個完整的對象進行分解,分解的每一個部分都是Intent所支持的數(shù)據(jù)類型。在序列化過程中需要實現(xiàn)序列化、反序列化和內(nèi)容描述
public class PicEntity implements Parcelable {    public String picURL;    public String middlePicURL;    public String smallPicURL;    //從序列化后得對象中創(chuàng)建原始對象    protected PicEntity(Parcel in) {        picURL = in.readString();        middlePicURL = in.readString();        smallPicURL = in.readString();    }    //反序列化的過程    public static final Creator<PicEntity> CREATOR = new Creator<PicEntity>() {        //從序列化后的對象返回原始對象        @Override        public PicEntity createFromParcel(Parcel in) {            return new PicEntity(in);        }        //創(chuàng)建指定長度的原始對象數(shù)組        @Override        public PicEntity[] newArray(int size) {            return new PicEntity[size];        }    };    //返回當前對象的內(nèi)容描述    @Override    public int describeContents() {        return 0;    }    //序列化的過程    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeString(picURL);        dest.writeString(middlePicURL);        dest.writeString(smallPicURL);    }}Intent、Bundle、Bitmap都是直接序列化的。List和Map也可序列化,里面的每個元素都是可序列化的。3、區(qū)別Serializable 是java序列化接口,將整個對象序列化,簡單開銷大,序列化和反序列化需要大量I/O操作。Parcelable是Android序列化方式,適合Android平臺。將對象的每個部分序列化,效率高,使用麻煩。三、BinderBinder類,實現(xiàn)了IBinder接口。主要是AIDL(多線程,多并發(fā)訪問)和Messenger(底層還是AIDL,單線程處理)作用:跨進程通信的一種方式(1)客戶端和服務(wù)端進行通信的媒介,bindService時,服務(wù)端返回一個Binder對象,客戶端客戶獲取數(shù)據(jù)。(2)ServiceManager連接 各種Manager(ActivityManager、WindowManager等)和對應(yīng)ManagerService的橋梁。四、Messenger信使,可以在不同的進程中傳遞Message對象,在Message中放入要傳遞的數(shù)據(jù)特點:對AIDL做了封裝,一次只能處理一個請求。流程圖:使用步驟:1、服務(wù)端
public class MessengerService extends Service {    private static String TAG = "MessengerService";    private Messenger messenger = new Messenger(new MessageHandler());    @Override    public void onCreate() {        super.onCreate();    }    @Nullable    @Override    public IBinder onBind(Intent intent) {    //返回這個messenger對象底層的Binder        return messenger.getBinder();    }    //處理服務(wù)端發(fā)送來的數(shù)據(jù)    private static class MessageHandler extends Handler{        @Override        public void handleMessage(Message msg) {            String myText = msg.getData().getString("msg");            LogUtil.i(TAG,"收到的消息:"+myText);            //回復消息            Messenger client = msg.replyTo;            Message replyMessage = Message.obtain(null,2);            Bundle bundle = new Bundle();            bundle.putString("reply","收到了消息了啊");            replyMessage.setData(bundle);            try {                //做出回復                client.send(replyMessage);            }catch (RemoteException e){                e.printStackTrace();            }        }    }}清單文件配置:
<service android:name=".service.MessengerService"    android:process=":remote"    ></service>2、客戶端
/** * * 用戶端 */public class MainActivity extends BaseActivity{    private Messenger messenger;    @Override    protected int getContentViewID() {        return R.layout.activity_main;    }    @Override    public void initView() {        super.initView();        Intent intent = new Intent(this, MessengerService.class);        bindService(intent,connection,BIND_AUTO_CREATE);    }    private Messenger replyMessenger = new Messenger(new MessageHandler());    private static class MessageHandler extends Handler {        @Override        public void handleMessage(Message msg) {            String myText = msg.getData().getString("reply");            LogUtil.i(TAG,"客戶端收到的消息:"+myText);        }    }    private ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //綁定成功后,用服務(wù)端返回的IBinder來創(chuàng)建一個Messenger            //通過這個Messenger向服務(wù)端發(fā)消息            messenger = new Messenger(service);            Message message = Message.obtain(null,1);            Bundle bundle = new Bundle();            bundle.putString("msg","ssssss");            message.setData(bundle);            //客戶端接收到服務(wù)端回復的消息            message.replyTo = replyMessenger;            try {                //發(fā)送消息                messenger.send(message);            }catch (RemoteException e){                e.printStackTrace();            }        }        @Override        public void onServiceDisconnected(ComponentName name) {            LogUtil.i("鏈接斷開");        }    };    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(connection);    }}五、AIDL:1、創(chuàng)建實體類,實現(xiàn)Parcelable
public class Book implements Parcelable {    public int bookId;    public String bookName;    public Book(int bookId,String bookName){        this.bookId=bookId;        this.bookName = bookName;    }    protected Book(Parcel in) {        bookId = in.readInt();        bookName = in.readString();    }    @Override    public String toString() {        return "["+bookId+"---"+bookName+"]";    }    public static final Creator<Book> CREATOR = new Creator<Book>() {        @Override        public Book createFromParcel(Parcel in) {            return new Book(in);        }        @Override        public Book[] newArray(int size) {            return new Book[size];        }    };    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeString(bookName);        dest.writeInt(bookId);    }}2、AIDL接口的實現(xiàn):(1)AIDL文件支持的數(shù)據(jù)類型基本數(shù)據(jù)類型(int、long、char、boolean、double等)String和CharSequenceArrayList : 里面的元素必須能被AIDL支持HashMapParcelable:實現(xiàn)了Parcelable接口的對象注:其中Parcelable對象和AIDL對象顯式import進來創(chuàng)建一個AIDL文件,將需要給客戶端調(diào)用的接口在AIDL文件中聲明
// IBookManager.aidlpackage com.example.hejian.demo2.aidl;//導入所需要使用的非默認支持數(shù)據(jù)類型的包import com.example.hejian.demo2.aidl.Book;interface IBookManager{List<Book> getBookList();void add(in Book book);}(2)如果有自定義Parcelable對象,必須建一個同名的AIDL文件
// Book.aidl//這個文件的作用是引入了一個序列化對象 Book 供其他的AIDL文件使用//注意:Book.aidl與Book.java的包名應(yīng)當是一樣的package com.example.hejian.demo2.aidl;parcelable Book;3、服務(wù)端創(chuàng)建一個Service,在Service中實現(xiàn)這個AIDL接口。注:AIDL方法是在服務(wù)端的Binder線程池中執(zhí)行,可能出現(xiàn)并發(fā)訪問的情況(可使用CopyOnWriteArrayList進行并發(fā)訪問)4、綁定服務(wù)端的Service,通過服務(wù)器返回的Binder對象轉(zhuǎn)成AIDL接口所需類型。5、專門刪除跨進程的listener的接口RemoteCallbackList。客戶端進程終止,自動移除客戶端注冊的listener原理:內(nèi)部有一個map專門保存所有的AIDL回調(diào),map的key時IBinder類型,value是Callback類型(真正的遠程listener)他們底層的Binder對象是同一個,將相同的key的listener刪除掉就可。
// IOnNewBookArrivedListener.aidlpackage com.example.hejian.aidldemo;// Declare any non-default types here with import statementsimport com.example.hejian.aidldemo.Book;//新書到了的監(jiān)聽interface IOnNewBookArrivedListener {    void onNewBookArrived(in Book newBook);}服務(wù)端Service:
/** * 服務(wù)端 */public class AIDLService extends Service {    private CopyOnWriteArrayList<Book> mBooks = new CopyOnWriteArrayList<>();    public final String TAG = this.getClass().getSimpleName();    private RemoteCallbackList<IOnNewBookArrivedListener> backListener = new RemoteCallbackList<>();    @Override    public void onCreate() {        super.onCreate();        mBooks.add(new Book(13,"思維"));        mBooks.add(new Book(23,"思維1"));    }    private Binder binder= new IBookManager.Stub(){        @Override        public List<Book> getBookList() throws RemoteException {            Log.e(TAG, "獲取到服務(wù)端list : " + mBooks.toString());            return mBooks;        }        @Override        public void add(Book book) throws RemoteException {            mBooks.add(book);            //通過監(jiān)聽通知所有的客戶端            final int N = backListener.beginBroadcast();            for (int i=0;i<N;i++){                IOnNewBookArrivedListener listener = backListener.getBroadcastItem(i);                listener.onNewBookArrived(book);            }            backListener.finishBroadcast();            Log.e(TAG, "增加一本以后,服務(wù)端list : " + mBooks.toString());        }        @Override        public void registListener(IOnNewBookArrivedListener listener) throws RemoteException {            backListener.register(listener);        }        @Override        public void unregistListener(IOnNewBookArrivedListener listener) throws RemoteException {            backListener.unregister(listener);        }    };    @Nullable    @Override    public IBinder onBind(Intent intent) {        return binder;    }}用戶端:
public class MainActivity extends AppCompatActivity {    //由AIDL文件生成的Java類    private IBookManager mBookManager = null;    //包含Book對象的list    private List<Book> mBooks = new ArrayList<>();    private static String TAG = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button = (Button)findViewById(R.id.button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                try {                    if (mBookManager!=null){                        mBooks.add(new Book(23,"新增的"));                        mBookManager.add(new Book(23,"新增的"));                    }                } catch (RemoteException e) {                    e.printStackTrace();                }                Log.e(TAG, "增加一本以后,客戶端list : "+mBooks.toString());            }        });    }    @Override    protected void onResume() {        super.onResume();        Intent intent = new Intent(this, AIDLService.class);        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);    }    private final ServiceConnection mServiceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.e(TAG, "service connected");            //將服務(wù)端返回的Binder對象轉(zhuǎn)成AIDL接口,然后通過接口掉方法            mBookManager = IBookManager.Stub.asInterface(service);            if (mBookManager != null) {                try {                    mBookManager.registListener(listener);                    mBooks = mBookManager.getBookList();                    Log.e(TAG, "獲取客戶端list:"+mBooks.toString());                } catch (RemoteException e) {                    e.printStackTrace();                }            }        }        @Override        public void onServiceDisconnected(ComponentName name) {            Log.e(TAG, "service disconnected");        }    };    private IOnNewBookArrivedListener listener = new IOnNewBookArrivedListener.Stub() {        @Override        public void onNewBookArrived(Book newBook) throws RemoteException {            Log.e(TAG,"監(jiān)聽到服務(wù)器加了一個書:"+newBook.toString());        }    };    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(mServiceConnection);    }}6、Binder死亡監(jiān)聽(1)設(shè)置DeathRecipient監(jiān)聽,在binderDied方法中重連遠程服務(wù)(在Binder線程池中被回調(diào))(2)在onServiceDisconnected中重連遠程服務(wù)7、遠程服務(wù)的權(quán)限驗證(1)例如在清單文件聲明權(quán)限,在Service的onBind方法中做權(quán)限驗證(2)在服務(wù)端onTransact方法驗證(3)獲取Uid和Pid,驗證客戶端包名等注意:由于客戶端onServiceConnected和onServiceDisConnected方法運行在UI線程,不能直接進行耗時操作服務(wù)端本身運行在Binder線程池中,可以執(zhí)行大量的耗時操作。注:開發(fā)藝術(shù)探索筆記整理


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 灵山县| 青龙| 福州市| 将乐县| 潜山县| 开鲁县| 商南县| 沽源县| 东至县| 平定县| 司法| 丹凤县| 宁武县| 绍兴县| 五莲县| 张家界市| 湄潭县| 连江县| 广丰县| 湄潭县| 上犹县| 平武县| 石门县| 锡林浩特市| 九江市| 调兵山市| 密山市| 洛隆县| 姚安县| 黑山县| 大洼县| 铜鼓县| 太仆寺旗| 锡林郭勒盟| 栾川县| 长武县| 辽中县| 玉门市| 海淀区| 焉耆| 盖州市|