Android 中 IPC 机制 (一)

1,080 阅读5分钟
原文链接: blog.csdn.net

1.Android中IPC简介

IPC含义为进程间通信或者跨进程通信,是指两个进程进行数据交换的过程。

什么是进程和线程?

线程:线程是CPU调度的最小单元,同时线程是一种有限的系统资源。

进程:一般只一个执行单元,在PC和移动设备上指一个程序或者一个应用

两者是包含与被包含的关系,一个进程可以包含多个线程

Android中主线程也叫UI线程,在UI线程中才能操作界面元素,如果在主线程中执行大量耗时任务,会造成界面无法响应,即ANR应用无响应,解决这个问题就要用到线程,把一些耗时任务放在线程中即可。

Android中进程间通信的方式是Binder,通过Binder可以轻松地实现进程间通信

2.Android中的多进程模式

(1)开启多进程模式

通过给四大组件指定android:process属性,开启多进程模式

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.zhoujian.ipc">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">


        <!--虽没指定process属性,运行在默认进程中,默认进程名为包名
        com.zhoujian.ipc
        -->

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <!--SecondActivity启动时,系统会为它创建一个单独的进程,进程名为:
        com.zhoujian.ipc:romote
        -->

        <activity android:name=".SecondActivity"
                  android:label="@string/app_name"
                  android:process=":romote"/>



        <!--ThirdActivity启动时,系统会为它创建一个单独的进程,进程名为:
        com.zhoujian.ipc.romote
        -->

        <activity android:name=".ThirdActivity"
                  android:label="@string/app_name"
                  android:process="com.zhoujian.ipc.romote"/>

    </application>

</manifest>

MainActivity.Java

package com.zhoujian.ipc;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity
{


    public static final String TAG = "MainActivity";
    private Button mStart_one;
    private Button mStart_two;


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG, "onCreate方法执行了");

        initViews();


        clickEvents();
    }

    private void clickEvents()
    {

        mStart_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,SecondActivity.class));
            }
        });


        mStart_two.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,ThirdActivity.class));
            }
        });

    }

    private void initViews()
    {
        mStart_one = (Button)findViewById(R.id.start_one);
        mStart_two = (Button)findViewById(R.id.start_two);

    }

    @Override
    protected void onRestart() {
        super.onRestart();

        Log.d(TAG, "onRestart方法执行了");
    }

    @Override
    protected void onStart() {
        super.onStart();

        Log.d(TAG, "onStart方法执行了");
    }

    @Override
    protected void onResume() {
        super.onResume();

        Log.d(TAG, "onResume方法执行了");
    }

    @Override
    protected void onPause() {
        super.onPause();

        Log.d(TAG, "onPause方法执行了");
    }

    @Override
    protected void onStop() {
        super.onStop();

        Log.d(TAG, "onStop方法执行了");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "onDestroy方法执行了");
    }

}

SecondActivity.java

package com.zhoujian.ipc;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class SecondActivity extends AppCompatActivity
{


    public static final String TAG = "SecondActivity";


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Log.d(TAG, "onCreate方法执行了");



    }

    @Override
    protected void onRestart() {
        super.onRestart();

        Log.d(TAG, "onRestart方法执行了");
    }

    @Override
    protected void onStart() {
        super.onStart();

        Log.d(TAG, "onStart方法执行了");
    }

    @Override
    protected void onResume() {
        super.onResume();

        Log.d(TAG, "onResume方法执行了");
    }

    @Override
    protected void onPause() {
        super.onPause();

        Log.d(TAG, "onPause方法执行了");
    }

    @Override
    protected void onStop() {
        super.onStop();

        Log.d(TAG, "onStop方法执行了");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "onDestroy方法执行了");
    }

}

ThirdActivity.java

package com.zhoujian.ipc;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class ThirdActivity extends AppCompatActivity
{


    public static final String TAG = "ThirdActivity";


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG, "onCreate方法执行了");
    }

    @Override
    protected void onRestart() {
        super.onRestart();

        Log.d(TAG, "onRestart方法执行了");
    }

    @Override
    protected void onStart() {
        super.onStart();

        Log.d(TAG, "onStart方法执行了");
    }

    @Override
    protected void onResume() {
        super.onResume();

        Log.d(TAG, "onResume方法执行了");
    }

    @Override
    protected void onPause() {
        super.onPause();

        Log.d(TAG, "onPause方法执行了");
    }

    @Override
    protected void onStop() {
        super.onStop();

        Log.d(TAG, "onStop方法执行了");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "onDestroy方法执行了");
    }

}

启动SecondActivity和ThirdActivty

通过shell命令来查看进程

命令为:adb shell ps | grep +包名

本例的包名为:com.zhoujian.ipc

命令为:adb shell ps | grep com.zhoujian.ipc

这里写图片描述

SecondActivity和ThirdActivity的 android:process属性分别为 android:process=”:romote”和 android:process=”com.zhoujian.ipc.romote”

两者的区别

首先,“:”含义是在当前进程名前面加上包名完整进程名com.zhoujian.ipc:romote。ThirdActivity的命名方式是一种完整的命名方式,不会附加包名信息。

其次,进程名以“:”开头的进程属于当前应用的私有进程,其他应用组件不可以和它跑在同一个进程中,而进程名不以“:”开头的进程属于全局进程,其它应用可以通过ShareUID方式和它跑在同一个进程中。

Android系统会为每一个应用分配一个唯一的UID,具有相同UID的应用才能共享数据,另个应用通过ShareUID跑在同一个进程中是有要求的,需要这两个应用有相同的ShareUID并且签名相同才可以

(1)多进程模式的运行机制

MainActivity.java和SecondAtivity.java属于不同的进程

首先,先来看一个例子

新建存放全局变量的类GlobalValue.java

package com.zhoujian.ipc;

/**
 * Created by zhoujian on 2017/2/24.
 */

public class GlobalValue
{
    public static int id = 1;
}

在MainActivity中将id重新赋值为2,然后,在SecondActivity中获取id的值,你会发现id值没变,还是1。

这个问题出现的原因是:SecondActivity运行在一个单独的进程中,Android为每一个应用分配了一个独立的虚拟机,或者说为每一个进程都分配一个独立的虚拟机,不同虚拟机在内存分配上有不同的地址空间,这就导致在不同虚拟机中访问同一个类的对象会产生多份副本。

一般来说,使用多进程会造成以下问题

(1)静态成员和单列模式完全失效

(2)线程同步机制完全失效

(3)SharePreferences的可靠性下降

(4)Application会多次创建

第一个问题,上面已经进行了分析

第二个问题和第一个问题类似,既然都不是一块内存了,那么不管锁对象还是锁全局都无法保证线程同步

第三个问题,因为SharePreferences不支持两个进程同时去执行写操作,否则会导致数据丢失

第四个问题,但一个组件跑在新的进程中的时候,由于系统要在创建新的进程同时分配独立的虚拟机,所以这个过程其实就是启动一个应用的过程,应用重新启动,那么自然会创建新的Application