Android開發(fā)之多進程詳解

相信很多做Android開發(fā)的同學對進程在Android中這個概念,都不怎么說的清楚,網(wǎng)路上有的說是一個應(yīng)用程序,這其實是不對的,為了研究Android中進程的概念,我這里寫了一個很簡單的代碼:

 <application
        android:name="com.example.nine.MyApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Light.NoTitleBar" >
        <activity
            android:name=".MyProcessActivityA"
            android:label="@string/app_name"
            android:process=":text.a" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.nine.MyProcessActivityB"
            android:process=":text.b" >
        </activity>
    </application>

這里我在aciticyA和B里分別加入了process標簽,意思就是讓這兩個activity運行在不同的進程里面。

下面是具體代碼:

package com.example.nine;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MyProcessActivityA extends Activity {
    private TextView tv1, tv2, tv3, tv4, tv5, tv6;
    private Button bt;
    private List<String> list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        initViews();
        initData();
    }

    private void initViews() {
        tv1 = (TextView) findViewById(R.id.tv1);
        tv2 = (TextView) findViewById(R.id.tv2);
        tv3 = (TextView) findViewById(R.id.tv3);
        tv4 = (TextView) findViewById(R.id.tv4);
        tv5 = (TextView) findViewById(R.id.tv5);
        tv6 = (TextView) findViewById(R.id.tv6);
        bt = (Button) findViewById(R.id.bt);
        bt.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                startActivity(new Intent(MyProcessActivityA.this,MyProcessActivityB.class));
            }
        });
    }

    private void initData() {
        list = new ArrayList<String>();
        for (int i = 0; i <1000000; i++) {
            list.add(i+"aaaaaaaaaaaaaaaaaaa");
        }
        Text.i = 1;
        tv1.setText("當前線程id:"+Thread.currentThread().getId());
        tv2.setText("當前進程Pid:"+android.os.Process.myPid());
        tv3.setText("當前進程名稱:"+MyUtil.getCurProcessName(this));
        tv4.setText("全局靜態(tài)變量i:"+Text.i);
        tv5.setText("當前申請的總內(nèi)存:"+Runtime.getRuntime().totalMemory()/1024/1024+"M");
        tv6.setText("單個進程分配的內(nèi)存上限:"+Runtime.getRuntime().maxMemory()/1024/1024+"M");
    }

}
package com.example.nine;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Bundle;
import android.widget.TextView;

public class MyProcessActivityB extends Activity{
    private TextView tv1, tv2, tv3, tv4, tv5, tv6;
    private List<String> list;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
        initViews();
        initData();
    }

    private void initViews() {
        tv1 = (TextView) findViewById(R.id.tv1);
        tv2 = (TextView) findViewById(R.id.tv2);
        tv3 = (TextView) findViewById(R.id.tv3);
        tv4 = (TextView) findViewById(R.id.tv4);
        tv5 = (TextView) findViewById(R.id.tv5);
        tv6 = (TextView) findViewById(R.id.tv6);
    }

    private void initData() {
        list = new ArrayList<String>();
        for (int i = 0; i <1000000; i++) {
            list.add(i+"aaaaaaaaaaaaaaaaaaa");
        }
        tv1.setText("當前線程id:"+Thread.currentThread().getId());
        tv2.setText("當前進程Pid:"+android.os.Process.myPid());
        tv3.setText("當前進程名稱:"+MyUtil.getCurProcessName(this));
        tv4.setText("全局靜態(tài)變量i:"+Text.i);
        tv5.setText("當前申請的總內(nèi)存:"+Runtime.getRuntime().totalMemory()/1024/1024+"M");
        tv6.setText("單個進程分配的內(nèi)存上限:"+Runtime.getRuntime().maxMemory()/1024/1024+"M");
    }

}
package com.example.nine;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyUtil {
public static String getCurProcessName(Context context) {
      int pid = android.os.Process.myPid();
      ActivityManager mActivityManager = (ActivityManager) context
        .getSystemService(Context.ACTIVITY_SERVICE);
      for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
        .getRunningAppProcesses()) {
       if (appProcess.pid == pid) {

        return appProcess.processName;
       }
      }
      return null;
     }
}



package com.example.nine;

import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.util.Log;

public class MyApplication extends Application{
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Log.e("ttext","Application onCreate"+"進程名稱"+MyUtil.getCurProcessName(getApplicationContext()));
    }
}
20160614170632383.png
20160614170700180.png
20160614170842872.png
20160614170911138.png
下面我們逐一進行分析:

1.這兩個activity雖然屬于不同的進程(text.a和text.b),但是我們看到打印出來的線程ID是一樣的,都是主線程的ID,說明四大組件不管屬于哪個進程,都一定是運行在主線程中的。

2.大家可以看到,我這個手機,分配給單個進程的內(nèi)存上限是192M,但是如果是兩個進程,142+142>192M,每個進程上限都是192M,互相獨立不影響;如果app特別復(fù)雜,可以考慮多開進程,提高內(nèi)存分配上限。

3.關(guān)于全局變量,Text.i,這是一個靜態(tài)變量,我在A里面設(shè)置成了1,但是在B里面引用,仍然初始化為0,說明不同進程之間不能共享全局變量。

4.關(guān)于application的創(chuàng)建問題,從最后的截圖可以看到,每個進程被加載,都會創(chuàng)建一個application對象,所以一個app里面不一定只有一個application對象。

5.關(guān)于application再說一點,同一個進程之間的全局變量的保存也最好不要用application對象來保存,因為如果app切換到后臺被殺死過后,application是會重建的,這個時候你保存的變量就會初始化。
同一個進程,當我們退出應(yīng)用程序過后,application其實并沒有立刻被殺死,這時你再點擊應(yīng)用進入,application并不會再次被重建,里面的還會保留以前的全局數(shù)據(jù),那么我們要怎么才能保證在退出程序的時候,把數(shù)據(jù)清空呢?
在退出的時候,關(guān)閉進程即可。

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    System.exit(0);
}

值得注意的是,System.exit(0);只能關(guān)閉當前進程。

另外,還有兩種方法可以關(guān)閉進程,分別是通過包名和PID。

//第一種
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
manager.killBackgroundProcesses(package);
//第二種
android.os.Process.killProcess(android.os.Process.myPid());

6.關(guān)于多進程之間數(shù)據(jù)傳遞的問題,這里我并沒有寫出demo,但是大體思路就是以下幾種:

a。通過Intent在四大組件中傳值。(這一點不管是同一個app里面的多進程還是不同app之間的多進程都可以)

值得注意的是,intent不能直接傳遞對象,如果要傳遞對象則要實現(xiàn)序列化的接口Parcelable或者是Serializable接口,本質(zhì)上都是轉(zhuǎn)化成字節(jié)流傳輸,這兩個接口不同之處在于Parcelable是內(nèi)存中讀寫速度較快但是占用內(nèi)存,Serializable是文件讀寫速度較慢但是內(nèi)存占用少。

b.通過本地存儲共享數(shù)據(jù).
數(shù)據(jù)庫或者xml都行。

c.關(guān)于網(wǎng)路上有的人說的什么多進程訪問本地文件,會有線程不安全的問題,這個其實并不正確,只要保證是在主線程中操作,就一定是線程安全的(原理參考第1點),當然如果你新建一個線程來讀寫,那就要用handler來保證線程安全了。

最后,我試著解釋下Android開發(fā)里面的進程的概念吧,其實谷歌官方是把Android里面的進程概念給弱化掉了,讓我們更加關(guān)心主線程,四大組件,不過強行要解釋的話,可以認為一個aplication對應(yīng)一個進程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內(nèi)容