Android 多进程的创建以及Messager的使用

1.多进程的应用场景

在Android开发中,大多数应用的所有组件都会在同一个进程中,但是比如播放音乐,或者需要进程常驻后台,又或者是一个大型应用里有地图模块、自定义WebView模块、大图浏览模块等等的应用场景,就需要多进程来让我们的应用更高效。

2.开启多进程

首先声明一个Service

public class MyService extends Service {

    private static final String TAG = "MyService";

    @Override
    public void onCreate() {
        Log.e(TAG, "myService onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "myService onStartCommand");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "myService onDestroy");
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

然后在清单文件中配置Service

<service
    android:name=".MyService"
    android:label="@string/app_name"
    android:process=":remote" />

接着在Activity中打开

public class MainActivity extends AppCompatActivity {

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

        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }
}

此时,在AndroidStudio的进程显示栏目中,便可以看到开启了两个线程,这里有一点需要注意的是,开启进程前的符号,:表示为私有进程,其他符号表示公有进程。

在开启多进程的时候,会出现一个小问题,就是Application会被调用两次。通过实现Application查看

public class MyApplication extends Application {

    private static final String TAG = "MyApplication";

    @Override
    public void onCreate() {
        super.onCreate();

        Log.e(TAG, "MyApplication onCreate");
    }
}

在Logcat下可以看到,两个进程下分别打印出了onCreate,这并不是我们想要的结果,因为在onCreate里会初始化的一些资源可能大多只是一个进程所需要的。我们可以拿到进程的属性,根据属性来判断目前是哪一个进程,然后Application初始化其所需要的对应资源。

public class MyApplication extends Application {

    private static final String TAG = "MyApplication";

    @Override
    public void onCreate() {
        super.onCreate();
        int pid = android.os.Process.myPid();
        Log.e(TAG, "MyApplication id is : " + pid);
        String processNameString = "";
        ActivityManager activityManager = (ActivityManager) this.getSystemService(getApplicationContext().ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : activityManager.getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                processNameString = appProcess.processName;
            }
        }
        if ("com.study.ipctest".equals(processNameString)) {
            Log.e(TAG, "main process");
        } else {
            Log.e(TAG, "remote process");
        }
    }
}

3.使用Messager实现进程之间的通信

创建好了多进程之后,那么不由的会想到,怎么在两个进程之间进行通信呢,我们先来看Messager,Messager是一种轻量级的IPC方案并对AIDL实现了简单的封装,Messager可以在不同的进程之间传递Message,而在Message中可以携带我们想要传递的信息。

首先我们创建一个MessengerService代表服务端,使用Handler来接收消息

public class MessengerService extends Service {

    public static final String TAG = "MessengerService";
    public static final int MSG_FROMCLIENT = 10086;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_FROMCLIENT: {
                    Log.e(TAG, "recieve message from client :" + msg.getData().get("msg"));
                    break;
                }
            }
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new Messenger(mHandler).getBinder();
    }
}

然后在代表客户端的MainActivity中像服务端发送一条消息

public class MainActivity extends AppCompatActivity {

    private Messenger mMessenger;

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

        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMessenger = new Messenger(service);
            Message message = Message.obtain(null, MessengerService.MSG_FROMCLIENT);
            Bundle mBundle = new Bundle();
            mBundle.putString("msg", "client send msg to service");
            message.setData(mBundle);
            try {
                mMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
    }
}

 这个时候,在Logcat下,选择服务端进程,就可以看到服务端收到客户端发过来的消息了,那么服务端怎么发消息给客户端呢,还是同样的思路,使用Messager发送,Handler接收。

public class MainActivity extends AppCompatActivity {

    private Messenger mMessenger;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MessengerService.MSG_FROMCLIENT:
                    Log.e(MessengerService.TAG, "client : " + msg.getData().get("rep"));
                    break;
            }
        }
    };

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

        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mMessenger = new Messenger(service);
            Message message = Message.obtain(null, MessengerService.MSG_FROMCLIENT);
            Bundle mBundle = new Bundle();
            Log.e(MessengerService.TAG, "client : " + "this is client, send a message to service");
            mBundle.putString("msg", "this is client, send a message to service");
            message.setData(mBundle);
            message.replyTo = new Messenger(mHandler); // 1
            try {
                mMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
    }
}

1处在发送给服务端的Message里必须带上客户端的Handler,这样便可以实现跨进程的消息传递。但是使用Messager来进行进程之间的通信,会有两个不足之处,第一是Messager是以串行的方式发送消息的,如果有大量的消息发送的话,显然是不合适的;第二是Messager只能用于进程之间的消息传递,却不能夸进程调用方法。所以Messager适用于轻量级的应用场景,那么针对于较复杂的场景,就需要使用AIDL。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值