您的位置:首页 > 移动开发 > Android开发

Android开启多进程

2015-12-26 15:58 537 查看
1. 为何要开启多进程

为何开启android应用要开启多进程,主要有以下几点:

单进程所分配的内存不够,需要更多的内存。在早期android系统只为一个单进程的应用分配了16M的可用内存,随着手机的硬件的提升和android系统的改进,虽然可分配内存越来越多,但仍旧可以通过开启多进程来获取更多的内存来处理自己App的业务

独立运行的组件,比如个推,它的服务会另开一个进程。

进行一些“不可告人”的操作的处理,比如双守护进程,来尽力使自己的应用不被系统杀死,或者获取用户的个人信息等其他信息。

2. 开启多进程

首先我们写一个Activity并启动一个service

[code]public class MyProcessActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_process);
        Intent myServiceIntent=new Intent(MyProcessActivity.this,MyService.class);
        this.startService(myServiceIntent);
    }
}


service的代码:

[code]public class MyService extends Service {

    private static final String TAG = "wangshu";
    @Override
    public void onCreate() {
        Log.i(TAG,"MyService is oncreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "MyProcessActivity is created: ");
        return START_STICKY;
    }
    @Override
    public void onDestroy() {
        Log.i(TAG,"OnDestory");
    }
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

}


最后我们只需要在AndroidManifest.xml中的配置 android:process就可以了

[code]<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.liuwangshu.myprogress" >

    <application
        android:allowBackup="true"
        android:name=".MyApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MyProcessActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".MyService"
            android:label="@string/app_name"
            android:process=":remote">
        </service>
    </application>
</manifest>


这里选择”remote”这个名字是随意主观的,你也可以取其他的名字。冒号“:”的含义是在当前进程名前面附上当前的包名。那么MyService的完整进程名为“com.example.liuwangshu.myprogress:remote”。我们也可以设置 android:process=”com.example.liuwangshu.myprogress.remote”,这是一种完整的命名方式。这两种命名也是有区别的,如果被设置的进程名是以“:”开头的,则这个新的进程对于这个应用来说是私有的,当它被需要或者这个服务需要在新进程中运行的时候,这个新进程将会被创建。如果这个进程的名字是以小写字符开头的,则这个服务将运行在一个以这个名字命名的全局的进程中,当然前提是它有相应的权限。这将允许在不同应用中的各种组件可以共享一个进程,从而减少资源的占用。

现在我们运行程序我们可以看到我们应用开启了两个进程



3. 开启多进程引出的问题

开启多进程确实很简单,但是同时也会带来一些问题,其中一个就是继承Application的类会执行多遍,我没在Application的子类里的oncreat方法中打log,来看看oncreat执行几遍

[code]public class MyApplication extends Application {
    private static final String TAG = "wangshu";
    @Override
    public void onCreate() {
        super.onCreate();
        int pid = android.os.Process.myPid(); 
        Log.i(TAG, "MyApplication is oncreate===="+"pid="+pid);
    }
 }


log中显示MyApplication 的onCreate执行了两次



但是现在很多的开发者都习惯在Application 的子类里去做应用的初始化和数据存储的操作,如果我们开启多个进程而让Application 的子类的各个回调方法都执行多次这显然是不多的,所以我们就应该区分进程,如果是应用的进程则做应用的操作,其他的进程(在这里是一个服务)就做其他的操作。首先我们是知道应用的进程的名字的,我们通过for循环来得到各个进程的名字,如果得到的进程的名字和我们应用进程名相同,我们就应该做应用的操作

[code]public class MyApplication extends Application {
    private static final String TAG = "wangshu";

    @Override
    public void onCreate() {
        super.onCreate();
        int pid = android.os.Process.myPid();
        Log.i(TAG, "MyApplication is oncreate====" + "pid=" + pid);
        String processNameString = "";
        ActivityManager mActivityManager = (ActivityManager) this.getSystemService(getApplicationContext().ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                processNameString = appProcess.processName;
                Log.i(TAG, "processName=" + processNameString);
            }
        }
        if ("com.example.liuwangshu.myprogress".equals(processNameString)) {
            Log.i(TAG, "processName=" + processNameString + "-----work");
        } else {
            Log.i(TAG, "processName=" + processNameString + "-----work");
        }
    }
}


来看看Log



总结一下开启多进程所带来的影响:

Application 会执行多次

多线程完全失效

静态成员和单例模式失效

SharedPreferences变得不可靠

第一条我们已经说过了,第二条也无需解释,第三条因为我们开启了多个进程,它们是运行在自己虚拟机上并分配了不同的地址空间,修改静态成员只会在自己的进程中有效,同样单例模式也是只有自己的进程中是单例,多个进程中就不能称之为单例了,因为很可能多个进程都会存在这个所谓的单例。第四条SharedPreferences并不支持并发的读取,多个进程可能存在并发的情况,这样SharedPreferences的读和写都变得不可靠。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: