1. 程式人生 > >安卓多程序與程序間通訊

安卓多程序與程序間通訊

1、安卓單程序的概念

        一般情況下一個應用程式就是一個程序這個程序名稱就是應用程式包名我們知道程序是系統分配資源和排程的基本單位所以每個程序都有自己獨立的資源和記憶體空間別的程序是不能任意訪問其他程序的記憶體和資源的

2、單程序存在的問題

        每個程序所能使用的資源是有限,特別是記憶體,安卓系統對使用者程序有嚴格的記憶體要求,超過此記憶體限制時,應用將OOM和崩潰。

        很多涉及到大圖片的頻繁操作或者需要讀取一大段資料在記憶體中使用時,很容易報OOM的問題。為了徹底地解決應用記憶體的問題,Android引入了多程序的概念,它允許在同一個應用內,為了分擔主程序的壓力,將佔用記憶體的某些頁面單獨開一個程序,比如大圖片的處理、子程序記錄執行軌跡等。

3、怎樣使用多程序

        Android多程序建立很簡單,只需要在AndroidManifest.xml的宣告四大元件的標籤中增加”android:process”屬性即可。命名之後,就成了一個單獨的程序。

process分私有程序和全域性程序:

3.1、私有程序的名稱前面有冒號,例如:

<service
            android:name="con.tt.business.record.RecordService"
            android:process="con.tt.business.record.RecordService:record"/>

3.2、全域性程序的名稱前面沒有冒號,例如:

<service
            android:name="con.tt.business.record.RecordService"
            android:process="con.tt.business.record.RecordService.record"/>

     為了節省系統記憶體,在退出該Activity的時候可以將其殺掉(如果沒有人為的呼叫程式碼殺掉該程序,在程式完全退出時該程序會被系統殺掉)。 通常情況沒有被殺掉的空程序也可以避免下次使用時再次建立程序, 這個有利有弊。

3.3、私有程序 與  全域性程序 的 區別

        全域性的程序,可以被其他應用共用。“共用”指的是不同的App的元件執行在同一個指定的程序中, 只不同的app的元件的 android:process 宣告的程序名稱是 相同的 且是 以小寫字母開頭。 那麼不同的APP的元件都可以進行這個 名稱的程序中。

需要注意的一點:
那麼我們先來看看Android5.0以下的原始碼,ActivityManagerService是如何關閉在應用退出後清理記憶體的

Process.killProcessQuiet(pid);  

應用退出後,ActivityManagerService就把主程序給殺死了,但是,在Android5.0以後,ActivityManagerService卻是這樣處理的:

Process.killProcessQuiet(app.pid);  
Process.killProcessGroup(app.info.uid, app.pid);  

在應用退出後,ActivityManagerService不僅把主程序給殺死,另外把主程序所屬的程序組一併殺死,這樣一來,由於子程序和主程序在同一程序組,子程序在做的事情,也就停止了。所以在Android5.0以後的手機應用在程序被殺死後,要採用其他方案。

4、多程序的缺點:

4.1、Application的onCreate()多次執行

多程序被建立好了,應用執行時就會對程序進行初始化,如果一個application中有多個程序,在進行全域性初始化時,多程序會被初始化多次。

        解決方法:通過判斷當前程序是不是 應用包名(預設程序名就是應用包名),來決定需不需要進行初始化相關的操作。

private String getCurrentProcessName() {
     String currentProcName = "";
     int pid = android.os.Process.myPid();
     ActivityManager manager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
     for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
        if (processInfo.pid == pid) {
            currentProcName = processInfo.processName;
            break;
        }
      }
      return currentProcName;
}

        如果子程序也需要一些初始化,則可根據程序名稱來分別做對應的 初始化 即可,並且只初始化當前程序需要的業務,即按照程序按需初始化。

4.2、除錯麻煩

多程序開發,除錯起來很麻煩,比如希望在子程序建立後的首行程式碼裡 新增斷點,這是做不到。 因為Android Studio新增偵錯程式的時候,會讓你選一個除錯的程序,而這時這個子程序還沒有啟動起來, 一旦你啟動起來後,首行程式碼就執行完畢了,就無法再新增除錯了

       解決方法:1、可以在子程序啟動後, 新增幾秒的延遲 再來啟動業務邏輯, 比如延遲5秒,而這5秒就是留給你去Android Studio中新增 斷點的

       2、除錯時關閉子程序,例如某些操作是在一個  Service時執行的,這時先把 service放到主程序中,等業務程式碼寫完了,再放到子程序 進行 功能測試。

4.3、不能記憶體共享

        同一個程序的多個執行緒是共享該程序的所有資源,但多個程序間記憶體是不可見的,也就是說多個程序間記憶體是不共享的。    會引起一些問題,如:靜態成員的失效。 

4.4、檔案共享問題。

 多程序情況下會出現兩個程序在同一時刻訪問同一個資料庫檔案的情況這就可能造成資源的競爭訪問導致諸如資料庫損壞資料丟失等在多執行緒的情況下我們有鎖機制控制資源的共享但是在多程序中比較難雖然有檔案鎖排隊等機制但是在Android裡很難實現解決辦法就是多程序的時候不併發訪問同一個檔案比如子程序涉及到操作資料庫就可以考慮呼叫主程序進行資料庫的操作

4.5、sharePreference不能在多程序中通用

      在主程序中往sharePreference存的值,在子程序不能立即可見。

     解決方法1:使用SharedPreferences時,SharedPreferences 在MODE_PRIVATE MODE_PUBLIC 之外其實還可以設定多程序的Flag,即 MODE_MULTI_PROCESS。

SharedPreferences myPrefs = context.getSharedPreferences(MY_FILE_NAME, Context.MODE_MULTI_PROCESS | Context.MODE_PRIVATE);

一旦我們設定了這個Flag,每次呼叫Context.getSharedPreferences 的時候系統會重新從SP檔案中讀入資料,因此我們在使用的時候每次讀取和存入都要使用Context.getSharedPreferences 重新獲取SP例項。即使是這樣,由於SP本質上並不是多程序安全的,所以還是無法保證資料的同步,因此該方法我們並沒有使用,我們也不推薦使用。

      解決方法2:

   如果SP不是多程序安全的,那麼是否有多程序安全的,又有SP功能的第三方專案呢。答案是有的,Tray——一個多程序安全的SharedPreferences,我們可以在Github上找到它,如果是AndroidStudio,可以直接使用Gradle引入,可謂是十分方便,如下是使用的程式碼,十分簡單,沒有apply commit,看起來比SP還要簡單。

但是最終我們並沒有選擇使用它,主要的原因是它需要minSdk 為15,而我們是支援sdk14的,所以只能果斷放棄了。

4.6、多程序的通訊問題

同一個程序的多個執行緒是共享該程序的所有資源,但多個程序間記憶體是不可見的,也就是說多個程序間記憶體是不共享的。    但通常我們的業務程式碼都是有關聯,很少有 能開啟多程序、同時又不需要程序程序通訊的 業務場景,因此這就需要多程序之間進行通訊。

Android中提供了三種程序通訊方法:

  • 系統實現。
  • AIDL(Android Interface Definition Language,Android介面定義語言):大部分應用程式不應該使用AIDL去建立一個繫結服務,因為它需要多執行緒能力,並可能導致一個更復雜的實現。
  • Messenger:利用Handler實現。(適用於多程序、單執行緒,不需要考慮執行緒安全),其底層基於AIDL。

4.7、多程序暖啟動的恢復問題 

  在主程序的MainActivity退出後,子程序還在執行,這時使用者又從手機桌面上點選應用圖示啟動了主程序,若業務功能中 主程序 與 子程序 有通訊,那麼此時 應該讓 上次斷開的主程序與子程序連線  再 重新連線上。  這裡就需要額外的判斷。

5、Messenger實現多程序通訊

1、第一步:在主程序中啟動  標記為多程序的 service

2、第二步:利用connectin中回撥的 IBinder 介面 建立一個 Messenger, 它用於 主程序 向 子程序 傳送訊息

3、第三步:子程序的Service的 onBind 建立一個 Messenger 並返回給主程序,這個Messager用於  子程序 向 主程序 傳送訊息

4、第四步:將子程序的service中建立好的 Messenger 通過 onBind 方法返回給 主程序 iBinder

5、第五步:建立連線

    主程序  必須 先發送一條 訊息到 子程序中, 子程序才知道 回傳訊息 應該 傳送給誰。  這時 主程序 就是 客戶端,  子程序  就是 服務端, 服務端在被動的等待客戶端 發起連線請求。  在服務端 收到 客戶端的 連線後,服務端需要 記錄下 客戶端的連結,以便 服務端 知道後續的訊息應該 傳送給誰。 

相關推薦

程序程序通訊

1、安卓單程序的概念         一般情況下,一個應用程式就是一個程序,這個程序名稱就是應用程式包名。我們知道程序是系統分配資源和排程的基本單位,所以每個程序都有自己獨立的資源和記憶體空間,別的程序是不能任意訪問其他程序的記憶體和資源的。 2、單程序存在的問題  

執行緒通訊程序之間通訊有什麼不同?分別怎麼實現?

**當一個程式第一次啟動的時候,Android會去動一個Linux進行和一個主執行緒,預設情況下,所有改程式元件都將在該程序和執行緒中 執行,同時Android會為每個應用程式分配一個單獨的Linux使用者,Android會盡量保留一個正在執行的程序,只在記憶體資源出現不足時,Andro

程序執行緒(三)——程序/執行緒通訊

在使用者空間中建立執行緒   用庫函式實現執行緒(《現代作業系統》 P61) #include<pthread.h> #include<stdio.h> #include<stdlib.h> #define NUMBER_OF_THREAD

java socket伺服器客戶端通訊

首先我們建立服務端, public class Main { public static void main(String[] args){ //啟動socket服務 try{ final ServerSo

PHP程序程序通訊

轉載自:http://wokill.cn/ PHP程序與程序間的通訊 一、引言 程序是具有獨立功能的程式與關於某個資料集合的一次執行活動。換句話講:在系統排程多個CPU時,一個程式的基本單元。程序對於大多數的語言都不是一個陌生的概念,作為”世界上最好的語言PHP”當然也例外 二、環

JAVA執行緒執行緒、程序程序通訊

I.執行緒與執行緒間通訊 一、基本概念以及執行緒與程序之間的區別聯絡: 關於程序和執行緒,首先從定義上理解就有所不同 1、程序是什麼? 是具有一定獨立功能的程式、它是系統進行資源分配和排程的一個獨立單位,重點在系統排程和單獨的單位,也就是說程序是可以獨 立執行的一段程式。

multiprocessing模組的程序程序

multiprocessing模組的Process方法 可以利用Proces方法在一個主程序中建立幾個子程序 from multiprocessing import Process import time def f1(name): time.sleep(2) print('Hell %s

前端如何.net後端通訊(一)

今天在公司工作,由於專案人手不夠,後端是使用.net開發的,然後一個寫交換的哥們不知道如何下手。 剛開始,我也是狗吃王八無從下口。 回想一下以前做的開發,任何與後端的通訊,無非就是找到後端的相應路徑,然後加上對應的引數,就能完成對應的功能。 例如: 一、在瀏覽器中,用百度搜

程序&執行緒通訊方式總結

# 管道( pipe ):管道是一種半雙工的通訊方式,資料只能單向流動,而且只能在具有親緣關係的程序間使用。程序的親緣關係通常是指父子程序關係。 # 有名管道 (namedpipe) : 有名管道也是半雙工的通訊方式,但是它允許無親緣關係程序間的通訊。 # 訊號量(semophore ) : 訊號量是一個計數

Linux的程序/執行緒通訊方式總結

Linux系統中的程序間通訊方式主要以下幾種: 同一主機上的程序通訊方式    * UNIX程序間通訊方式: 包括管道(PIPE), 有名管道(FIFO), 和訊號(Signal)    * System V程序通訊方式:包括訊號量(Semaphore), 訊息佇列

虛擬機Hyper-V沖突

viso 運行 沒有 div 安卓 虛擬機 gpo 虛擬 服務器   經過各種經驗,哪個安卓虛擬機跟Hyper-V都存在著沖突。   解決方案一   程序中卸載Hyper-V,之後還要再配置太麻煩。   解決方案二   1、關掉Hyper-V的啟動項,命令如下。   bcd

快速排序冒泡排序

java int end star ear cal ber instance pretty main 冒泡排序 private void swap(int[] arrays, int i, int j) { int temp;

使用飛豬動態IP修改器修改夜神開模擬器IP地址圖文教程

很多玩家一因為想上多個賬戶但是被限制使用了夜神多開模擬器,但是還是無法登入多個賬戶或者無法正常組隊等等問題,那是因為多開了但是模擬器 IP地址是一樣的問題造成的!所以今天教大家如何在模擬器上修改模擬器地址,讓每個多開的模擬器中地址都不一樣! 第一,安裝夜神多開模擬器。 第二, 多開的模

觸控事件單擊事件的區別

在學習了安卓的觸控事件和單擊事件後,我做了一個小實驗,從中總結出它們之間的區別。 實驗如下: 首先在activity_main.xml檔案中製作一個簡單的按鈕 在Java  class檔案中設定對按鈕的單擊監聽,和觸控監聽: package com.example.a

客戶端開發端connect

開發端 import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import jav

作業系統之程序程序控制

一、程序概念 引子 程式執行在併發環境中的問題 (1)執行過程不確定 (2)結果不可再現 1.程序定義   程序是程式在某個資料集合上的一次執行活動。資料集合是指軟硬體環境,多個程序共存或共享的環境。 2.程序的特徵 (1)動態性   程序是程式的一次執行過程,動態產生且動態消亡; (2)併發

Studio ADB模擬器的常見問題

       安卓開發過程中,很多小夥伴都是用模擬器進行測試,但是,經常碰到模擬器檢測不到,adb異常等問題,難受有木有。                   &nb

【Python】程序程序池的屬性方法及注意事項

1、程序的概念       程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。在早期面向程序設計的計算機結構中,程序是程式

快速排序氣泡排序

直接上程式碼~ 氣泡排序 private void swap(int[] arrays, int i, int j) { int temp; temp = ar

Linux 程序程序排程詳解

1、引言 程序:是程式執行時的一個例項,可以看作充分描述程式已經執行到何種程度的資料結構的彙集。從核心觀點看,程序的目的就是擔當分配系統資源(CPU時間、記憶體等)的實體。 當一個程序建立時,它獲得一個父程序地址空間的副本。共享正文段(程式碼段),但並不執行