美文网首页Android开发Android开发经验谈Android技术知识
如何开启多进程?应用是否可以开启N个进程?

如何开启多进程?应用是否可以开启N个进程?

作者: InFatuated | 来源:发表于2020-04-23 14:00 被阅读0次

    开启多进程
    首先我们写一个Activity并启动一个service

    package com.example.infatuated;
    
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent MyServiceIntent = new Intent(this, MyService.class);
            this.startService(MyServiceIntent);
        }
    }
    

    service的代码:

    package com.example.infatuated;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.support.annotation.Nullable;
    import android.util.Log;
    
    
    
    public class MyService extends Service {
    
        private static final String TAG = "qmsggg";
    
        @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, "ODestroy");
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    

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

    <application
        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/AppTheme">
        <activity android:name=".MainActivity">
            <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=":test"/>
    </application>
    

    需要特别说明的是,android:process=":test" 中的test名字是自定义的,而冒号":"的含义是当前进程名前附加上当前的包名。那么刚刚所创建出的Service的完整进程名就为com.example.infatuated:test.
    当然你也可以自己设置完整地进程名,如android:process="com.example.double:test"这便是一种完整地命名方式。
    而更重要的是两种命名方式的区别在于:

    • ":"开头的,则这个新的进程,对于这个应用来说是私有的,当它被需要或者这个服务需要在新进程中运行- 时,这个新进程就会被创建。
    • 如果这个进程的名字是以小写字符开头的,则这个服务将在一个以该名字命名的全局的进程中运行。当然前提是,它要有相应的权限,这将允许它在不同应用中的各个组件可以共享一个进程。从而减少资源的占用。

    接下来我们测试验证一下:

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

    日志结果如下:

    多进程log1.png

    可以看到MyApplication的OnCreate方法执行了两次。
    分别是在com.example.infatuated和com.example.infatuated:test 两个进程之中各执行了一次。
    所以这就衍生出了一个问题,很多开发者都习惯在Application的子类里面去做相应的初始化和数据化存储操作,如果我们开启多个进程让Application的子类各个回调方法都执行多次,这显然是有问题的。
    所以,我们应该区分进程,如果是应用进程,则做应用的相关操作,如果是其他进程(在这里是一个服务),就做其他的操作

    package com.example.infatuated;
    
    import android.app.ActivityManager;
    import android.app.Application;
    import android.util.Log;
    
    public class MyApplication extends Application {
      private static final String TAG = "MyApplication";
        @Override
        public void onCreate() {
            super.onCreate();
            int pid = android.os.Process.myPid();
            Log.i(TAG, "MyApplication is onCreate===="+"pid="+pid);
    
            String processnameString = "";
            ActivityManager manager =(ActivityManager)this.getSystemService(getApplicationContext().ACTIVITY_SERVICE);
            for (ActivityManager.RunningAppProcessInfo appProcessInfo : manager.getRunningAppProcesses()) {
                if (appProcessInfo.pid == pid) {
                    processnameString = appProcessInfo.processName;
                    Log.i(TAG, "processName=" + processnameString);
                }
            }
            if ("com.example.infatuated:test".equals(processnameString)) {
                Log.i(TAG, "processName = " + processnameString);
            }
        }
    
    多进程log2.png
    • 虚拟机上分配了不同的地址空间,修改静态成员只会在自己的进程中有效,同样单例模式也只有在自己的进程中是单例,多个进程就不能称之为单例了,因为很可能多个进程都会存在这个所谓的单例。
    • 于此同时因为SharedPreferences并不支持并发的读写缘故,在多个进程的使用过程中,就可能存在并发的情况,这样SharedPreferences的读写就会变得不可靠。

    总结:

    • 所以最后我们可以回答一开始提出的问题,一个应用程序能否开启多个进程,答案是:可以的
    • 然而还有一点需要说明的是,因为多个进程首先会拥有多个Application,数据会被初始化多次,其次进程之间的通信又比较麻烦,再者每一个进程都有其单独的虚拟机,多个进程自然也会消耗较多的内存。

    相关文章

      网友评论

        本文标题:如何开启多进程?应用是否可以开启N个进程?

        本文链接:https://www.haomeiwen.com/subject/jjeiyctx.html