日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 跨进程通信大总结

發布時間:2024/9/30 Android 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 跨进程通信大总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/111553746
本文出自【趙彥軍的博客】

文章目錄

    • 1、Android進程
    • 2、修改Android默認進程
    • 3、指定activity、Service進程
    • 4、activity進程間通信
    • 5、AIDL 簡介
    • 6、activity、service 進程間通信 AIDL
    • 7、AIDL 傳遞復雜對象
    • 8、SharedPreferences 跨進程
    • 9、廣播跨進程
    • 10、ContentProvider跨進程
      • 什么是ContentProvider ?
      • ContentProvider什么作用?
      • ContentProvider原理
      • ContentProvider優秀文章鏈接
    • 11、Socket跨進程通信
    • 12、文件共享跨進程
    • 13、Bundle跨進程
    • 14、MMKV

1、Android進程

android {compileSdkVersion 29buildToolsVersion "29.0.3"defaultConfig {applicationId "com.zhaoyanjun"minSdkVersion 16targetSdkVersion 29versionCode 1versionName "1.0"} }

applicationId 為:com.zhaoyanjun,那項目運行起來,所有的 activity 、service 默認運行在 com.zhaoyanjun 進程.

工具類:

package com.zhaoyanjun;import java.io.FileInputStream; import java.io.IOException;/*** @author yanjun.zhao* @time 2020/12/16 11:01 AM* @desc*/ public class Process {/*** 獲取當前進程名* @return*/public static String getCurrentProcessName() {FileInputStream in = null;try {String fn = "/proc/self/cmdline";in = new FileInputStream(fn);byte[] buffer = new byte[256];int len = 0;int b;while ((b = in.read()) > 0 && len < buffer.length) {buffer[len++] = (byte) b;}if (len > 0) {String s = new String(buffer, 0, len, "UTF-8");return s;}} catch (Throwable e) {e.printStackTrace();} finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}return null;} }

2、修改Android默認進程

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.zhaoyanjun"><applicationandroid:process=":appProcess"android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.RecyclerViewDemo"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application> </manifest>

在 application 標簽下添加 android:process 屬性可以修改Android默認的進程名字。進程的名字為:com.zhaoyanjun:appProcess , 這個修改是全局的,所有 activity 都默認運行在這個進程中。

3、指定activity、Service進程

activity 指定進程

<activityandroid:process=":remote"android:name=".MainActivity2"> </activity>


service 指定進程

<serviceandroid:process=":remote_service"android:name=".LibraryService"> </service>

4、activity進程間通信

MainActivity有一個 button 按鈕,點擊跳轉到 MainActivity2

//MainActivity代碼 findViewById<Button>(R.id.bt1).setOnClickListener {var intent = Intent(this, MainActivity2::class.java)intent.putExtra("key", "value1")startActivity(intent) }

MainActivity2 指定進程

<activityandroid:process=":remote"android:name=".MainActivity2"> </activity>

MainActivity2 邏輯

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main2)var value = intent.getStringExtra("key")Log.d("zhaoyanjun", "MainActivity2 進程: ${Process.getCurrentProcessName()} 獲取值: $value") }

日志:

D/zhaoyanjun: MainActivity2 進程: com.zhaoyanjun:remote 獲取值: value1

5、AIDL 簡介

AIDL的語法十分簡單,與Java語言基本保持一致,需要記住的規則有以下幾點:

1、AIDL文件以 .aidl 為后綴名

2、 AIDL支持的數據類型分為如下幾種:

  • 八種基本數據類型:byte、char、short、int、long、float、double、boolean
    String,CharSequence
  • 實現了Parcelable接口的數據類型
  • List 類型。List承載的數據必須是AIDL支持的類型,或者是其它聲明的AIDL對象
  • Map類型。Map承載的數據必須是AIDL支持的類型,或者是其它聲明的AIDL對象

3、AIDL文件可以分為兩類。一類用來聲明實現了Parcelable接口的數據類型,以供其他AIDL文件使用那些非默認支持的數據類型。還有一類是用來定義接口方法,聲明要暴露哪些接口給客戶端調用,定向Tag就是用來標注這些方法的參數值。

3、定向Tag。定向Tag表示在跨進程通信中數據的流向,用于標注方法的參數值,分為 in、out、inout 三種。

  • 其中 in 表示數據只能由客戶端流向服務端,
  • out 表示數據只能由服務端流向客戶端,而 inout 則表示數據可在服務端與客戶端之間雙向流通。此外,如果AIDL方法接口的參數值類型是:基本數據類型、String、CharSequence或者其他AIDL文件定義的方法接口,那么這些參數值的定向 Tag 默認是且只能是 in,所以除了這些類型外,其他參數值都需要明確標注使用哪種定向Tag。定向Tag具體的使用差別后邊會有介紹

4、明確導包。在AIDL文件中需要明確標明引用到的數據類型所在的包名,即使兩個文件處在同個包名下

6、activity、service 進程間通信 AIDL

創建 IBookAidlInterface.aidl文件
創建 IBookAidlInterface 完成后,會在 main 目錄下,創建 aidl 文件夾,并且會創建同名的包名,如下:

我們把默認的 basicTypes 方法刪除,修改如下

interface IBookAidlInterface {String getTitle();void setTitle(String title); }

下面創建 Service , 并指定進程名字:

<serviceandroid:name=".MyService"android:enabled="true"android:exported="true"android:process=":remote" />

MyService 如下:

class MyService : Service() {private var binder: Binder = object : IBookAidlInterface.Stub() {override fun getTitle(): String {return "aidl->title"}override fun setTitle(title: String?) {Log.d("aidl", "service-setTitle:$title")}}override fun onBind(intent: Intent): IBinder {return binder}override fun onCreate() {super.onCreate()} }

MainActivity 綁定Service

class MainActivity : AppCompatActivity() {private var iBookAidlInterface: IBookAidlInterface? = nullprivate var serviceConnection: ServiceConnection = object : ServiceConnection {override fun onServiceDisconnected(name: ComponentName?) {}override fun onServiceConnected(name: ComponentName?, service: IBinder?) {iBookAidlInterface = IBookAidlInterface.Stub.asInterface(service)var name = iBookAidlInterface?.titleLog.d("aidl", "getTitle: $name")iBookAidlInterface?.title = "我是一個title"}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)bindService()}/*** 綁定服務*/private fun bindService() {var intent = Intent(this, MyService::class.java)bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)}override fun onDestroy() {super.onDestroy()unbindService(serviceConnection)} }

運行項目,日志如下:


可以看到,子進程 Service 和 主進程的 Activity 已經可以通信了。
github 地址:https://github.com/zyj1609wz/AndroidMultiProgress

7、AIDL 傳遞復雜對象

首先創建 Book 類,并且實現 Parcelable 接口。這里要注意,一定要實現 Parcelable 接口,因為只有實現 Parcelable 的復雜對象才能在 AIDL 中傳遞。

public class Book implements Parcelable {public String title;Book() {}protected Book(Parcel in) {title = in.readString();}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(title);}@Overridepublic int describeContents() {return 0;}public static final Creator<Book> CREATOR = new Creator<Book>() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}}; }

同時在 aidl 目錄中定義 Book.aidl 文件,并且聲明 parcelable 屬性。Book.aidl文件如下:

package com.yanjun.progress;parcelable Book;

下面我們修改 IBookAidlInterface.aidl 的方法,如下:

interface IBookAidlInterface {String getTitle();void setTitle(String title);Book getBook();void setBook(in Book book); }

需要注意的是 setBook方法,一定要聲明 Book 對象是 in屬性,表明是 book 對象是從客戶端流向服務端。

最后在 Service 里面實現接口就行了,如下:

class MyService : Service() {private var binder: Binder = object : IBookAidlInterface.Stub() {override fun getTitle(): String {return "aidl->title"}override fun setTitle(title: String?) {Log.d("aidl", "service-setTitle:$title")}override fun getBook(): Book {var book = Book()book.title = "書的名字"return book}override fun setBook(book: Book?) {}}override fun onBind(intent: Intent): IBinder ?{return binder}override fun onCreate() {super.onCreate()} }

demo github 地址:https://github.com/zyj1609wz/AndroidMultiProgress

8、SharedPreferences 跨進程

SharedPreferences要實現跨進程通信,要遵循文件名字相同的規則。而且是同一個應用,兩個進程間。
SharedPreferences之所以能實現跨進程,是因為SharedPreferences 數據存在SD卡的磁盤中,兩個進程共用一個文件。

注意事項:

  • 雖然 SharedPreferences 可以實現跨進程,但是 Google 官方不建議使用,因為 Google 認為多個進程讀同一個文件都是不安全的,Android 不保證該模式總是能正確的工作,建議使用 ContentProvider 替代多進程之間文件的共享。

額外話題 SharedPreferences 優化:

  • commit 是把內容同步提交到硬盤的,返回 boolean 表明修改是否提交成功
  • apply先立即把修改提交到內存,然后開啟一個異步的線程提交到硬盤,并且如果提交失敗,你不會收到任何通知,apply沒有返回值 。
  • 使用了apply方式異步寫sp的時候,每次apply()調用都會新增一個finisher。在有些系統生命周期事件發生的時候都會去檢查已經提交的apply寫操作是否完成,如果沒有完成則阻塞主線程,造成 ANR
  • 當一個文件較大時,首次讀取可能會較慢,每次寫入也會較慢
  • 在不同模塊使用多個文件存儲的情況下,那么未被使用到的模塊,不會被讀取進內存
  • 當存儲的value為json或者html形式時,由于特殊符號較多,會占用更多的字符

如何解決 ANR :

  • 如果處理 SP的時候,使用commit方法替代apply,在保證調用時線程正確處理,并保證同一文件不使用多個線程寫入的情況下,不會出現該ANR。
  • 自查是否有一下子修改多個key-value且apply多次的情況,如有,可合并為put多次但apply一次

9、廣播跨進程

Context.sendBroadcast()
發送的是普通廣播,所有訂閱者都有機會獲得并進行處理

10、ContentProvider跨進程

什么是ContentProvider ?

即 內容提供者,是 Android 四大組件之一

ContentProvider什么作用?

進程間 進行數據交互 & 共享,即跨進程通信

ContentProvider原理

ContentProvider的底層原理 = Android中的Binder機制

ContentProvider優秀文章鏈接

本來是想總結一下的,但是我發現了一篇寫的很好的文章:
建議把文章和評論都看看,很有收獲。

Android:關于ContentProvider的知識都在這里了!
Android中使用Contentprovider導致進程被殺死

11、Socket跨進程通信

優點:

  • 功能強大,可通過網絡傳輸字節流,支持一對多實時并發通信

缺點:

  • 實現細節步驟稍繁瑣,不支持直接的RPC

適用場景:

  • 網絡間的數據交換

12、文件共享跨進程

優點

  • 簡單易用

缺點:

  • 不適用高并發場景,并且無法做到進程間即時通信

適用場景:

  • 適用于無關發的情況下,交換簡單的數據,對實時性要求不高的場景。

13、Bundle跨進程

優點

  • 簡單易用

缺點:

  • 只能傳輸Bundle支持的數據類型

適用場景:

  • 四大組件間的進程間通信

14、MMKV

MMKV是國內微信團隊開源的高性能 key-value組件,良好的支持Android跨進程通信,具體使用方法就自己看文檔吧,這里不贅述了。

github: https://github.com/Tencent/MMKV/
中文文檔:MMKV中文文檔

總結

以上是生活随笔為你收集整理的Android 跨进程通信大总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。