Handler进程间通信

          Handler在线程间通信很常用,进程间通信却用的很少,书中有介绍自己试用了一下,觉得不是很好用,而且底层也是AIDL,也是Binder,其实没差别,还很绕。

 客户端为一个Acitvity 代码如下


package com.xue.qin.demo.message;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.widget.Button;

/**
 * Created by xue.qin on 2017/6/12.
 */

public class ClientActivity extends Activity implements View.OnClickListener {
    private static final String TAG = "ClientActivity";
    Button mButton;
    private Messenger mService;
    private Messenger mMessenger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message msgFromServer) {
            Log.i(TAG, "Client Get Message :" + msgFromServer);
            super.handleMessage(msgFromServer);
        }
    });

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mai_activity_layout);
        mButton = (Button) findViewById(R.id.sendMessage);
        mButton.setOnClickListener(this);
        Intent startService = new Intent("remoteService");
        startService.setPackage(getPackageName());
        bindService(startService, mConn, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);
            Log.i(TAG, "onServiceConnected()");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
            Log.i(TAG, "onServiceDisconnected()");
        }
    };

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

    @Override
    public void onClick(View v) {
        try {
            if (mService != null) {
                Message msg = Message.obtain(); //从消息池中取出最靠前的消息,如果没有消息就新建一个,然后重新赋值
                msg.what = 1234;
                msg.arg1 = 1;
                msg.arg2 = 2;
                msg.replyTo = mMessenger;
                mService.send(msg);

            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

在声明一个服务端的Service,是在不同进程Xml写成如下

<service
            android:name=".ServerService"
            android:process=".remote">
            <intent-filter>
                <action android:name="remoteService"></action>
            </intent-filter>
        </service>


Service代码如下:

package com.xue.qin.demo.message;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by xue.qin on 2017/6/12.
 */

public class ServerService extends Service {
    private static final String TAG = "ServerService";
    Messenger mMessenger = new Messenger(new Handler() {
        @Override
        public void handleMessage(Message fromClient) {
            Log.i(TAG, "msg = " + fromClient);
            try {
                Message toClient = Message.obtain();
                toClient.what = 1234;
                toClient.arg1 = fromClient.arg1 + 1;
                toClient.arg2 = fromClient.arg2 + 1;
                fromClient.replyTo.send(toClient);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            super.handleMessage(fromClient);
        }
    });

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

}



因为是AIDL,本质应该是相同的,那么走一遍AIDL的流程,就明白了。

1)绑定Service。

2)返回onBind() 返回 Binder,这里和AIDL不一样是Messenger获得的BInder,去看一下源码是怎么回事。

Messenger.java

public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }

Messenger的声明实例使用了这个构造函数, 去看一下Handler里个getIMessenger()。

Handler.java

final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

这里new的这个内部类是这样的。

private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

这个就是是AIDL的生成的BInder类,native方法,没去看了。可以肯定的是这里的参数msg就是到底层转了一圈回来的客户端msg。

那它一定有个aidl文件,叫IMessenger.aidl,这个Handler类都没有引用包,那么应该就在同一个包里面了,果然找到了,代码如下。

文件位置:alps/frameworks/base/core/java/android/os


/* //device/java/android/android/app/IActivityPendingResult.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

隐藏的接口, 其中AIDL的方法还提供了oneway这个关键字,可以用关键字oneway来标明远程调用的行为属性,使用了该关键字,那么远程调用将仅仅是调用所需的数据传输过来并立即返回,而不会等待结果的返回,也即是说不会阻塞远程线程的运行。

这点和没有标记oneway的挂起等待返回,是不一样的。

就一个方法 send(),再往后就是BInder转发了,好的到这知道服务端这边返回的了。

3)客户端接收Binder。


@Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);
            Log.i(TAG, "onServiceConnected()");
        }

绑定成功接收返回的binder,看一下这个构造函数。

public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }

和AIDL一模一样,将这个Ibinder接收过来只有装饰了起来。猜测,客户端发送时就是要用这个target装饰成的Proxy的send来转发到服务端了,看一下是不是这样。

3)客户端调用本地方法。

try {
            if (mService != null) {
                Message msg = Message.obtain(); //从消息池中取出最靠前的消息,如果没有消息就新建一个,然后重新赋值
                msg.what = 1234;
                msg.arg1 = 1;
                msg.arg2 = 2;
                msg.replyTo = mMessenger;
                mService.send(msg);

            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }

这里mService.send(msg),看一眼源码

    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }
果然是这个代理发送的。

4)服务端 由Binder来映射调用。还记得之前服务端的Messenger里的Handler里的Stub吗,再粘一遍,这里就调用自己发送sendMessenge了。

private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }


这个服务端的Handler就可以接收到了,因为现在已经是本地发送与接收了。

5)服务端处理返回结果。

这里虽然不会挂起,但是也还是可以返回结果的,什么时候接收到就不一定了,Handler本就是这样。

服务端向客户端发送的代码

try {
                Message toClient = Message.obtain();
                toClient.what = 1234;
                toClient.arg1 = fromClient.arg1 + 1;
                toClient.arg2 = fromClient.arg2 + 1;
                fromClient.replyTo.send(toClient);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

replyTo是客户端发过来的,这里的调用时调用的Messenger里的Handler里的sendMessage,客户端肯定是可以收到的,当然也是在底层转了一圈,但是在应用这边,可以理解为就是ClientActivity 中的 Handler。


6)客户端接收,本地Handler本地接收。没问题。

这就完成了一次通信,这种通信觉得好绕而且不同步,没用过,看到书上写的,就看了一下。


验证一下,看看从Service返回的值。是不是加了1

01-01 20:36:53.107 12387-12387/com.xue.qin.demo.message I/ClientActivity: Client Get Message :{ when=-1ms what=1234 arg1=2 arg2=3 target=com.xue.qin.demo.message.ClientActivity$1 }

OK






  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 中,可以使用 Handler 进行进程间通信。以下是使用 Handler 进行进程间通信的基本步骤: 1. 在发送方进程中创建 Handler 对象,并在其构造函数中传递一个 Looper 对象。这个 Looper 对象可以通过调用 Looper.myLooper() 或 Looper.getMainLooper() 方法获取。 2. 在接收方进程中创建一个 Messenger 对象,将其作为参数传递给发送方进程的 Handler 对象的构造函数。 3. 在发送方进程中,通过 Messenger.send() 方法向接收方进程发送消息。在发送消息时,需要创建一个 Message 对象,并将其传递给 Messenger.send() 方法。 4. 在接收方进程中,需要创建一个 Handler 对象,并在其 handleMessage() 方法中处理消息。在创建 Handler 对象时,需要将当前线程的 Looper 对象作为参数传递给其构造函数。 5. 在接收方进程中,通过 Messenger 的 bindService() 方法来连接发送方进程的服务,从而接收发送方进程发来的消息。 下面是一个简单的示例代码,用于演示如何在两个进程之间使用 Handler 进行通信: 在发送方进程中: ``` // 创建 Handler 对象 Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { // 处理接收到的消息 } }; // 创建 Messenger 对象 Messenger messenger = new Messenger(handler); // 发送消息 Message message = Message.obtain(); messenger.send(message); ``` 在接收方进程中: ``` // 创建 Handler 对象 Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { // 处理接收到的消息 } }; // 创建 Messenger 对象 Messenger messenger = new Messenger(handler); // 绑定发送方进程的服务 Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.sender", "com.example.sender.MyService")); bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 连接成功,保存 Messenger 对象 messenger = new Messenger(service); } @Override public void onServiceDisconnected(ComponentName name) { // 连接断开 } }, Context.BIND_AUTO_CREATE); ``` 注意:在进行进程间通信时,需要使用 AIDL 接口来定义消息的格式。具体的实现方式超出了本回答的范围,可以查阅相关文档进行学习。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值