Android进程使用Messenger通信

欢迎Follow我的GitHub, 关注我的简书. 其余参考Android目录.

Messenger

本文的合集已经编著成书,高级Android开发强化实战,欢迎各位读友的建议和指导。在京东即可购买:https://item.jd.com/12385680.html

Android

进程之间不能共享内存数据, 但是可以进行通信, 除了简单的Intent通信, 也可以使用Messenger, Messenger基于AIDL实现, 顺序执行, 不支持并发. 为了区分通信的始末, 我们暂定发送数据是客户端, 接收数据是服务端. 本文介绍Messenger的使用方式, 含有Demo.

本文源码的GitHub下载地址


客户端

客户端发送数据到服务端, 服务端收到数据反馈回客户端.

接收反馈数据

MainActivity作为客户端, 发送信息. 首先创建消息的Handler类, 用于接收服务端的反馈, 继承Handler, 重写handleMessage方法, msg.what类型, msg.getData()数据.

private static class MessengerHandler extends Handler {
    private Context mContext;

    public MessengerHandler(Context context) {
        mContext = context.getApplicationContext();
    }

    @Override public void handleMessage(Message msg) {
        switch (msg.what) {
            case ParasConsts.MSG_FROM_SERVICE:
                String content = String.valueOf("客户端 - 收到信息: " + msg.getData().getString(ParasConsts.REPLY_ARG));
                Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show();
                break;
            default:
                super.handleMessage(msg);
                break;
        }
    }
}

使用Handler创建Messenger.

mReplyMessenger = new Messenger(new MessengerHandler(getApplicationContext()));
// ...
msg.replyTo = mReplyMessenger;

连接服务发送数据

创建ServiceConnection类, 实现onServiceConnected方法. 创建信使Messenger, 创建消息Message, 在Message中添加序列化数据msg.setData(), 设置接收反馈msg.replyTo. Messenger发送数据send.

private ServiceConnection mConnection = new ServiceConnection() {
    @Override public void onServiceConnected(ComponentName name, IBinder service) {
        mMessenger = new Messenger(service);
        Message msg = Message.obtain(null, ParasConsts.MSG_FROM_CLIENT);
        Bundle data = new Bundle();
        data.putString(ParasConsts.MSG_ARG, "Hello, I'm Spike, your friends.");
        msg.setData(data);

        // 需要设置Reply的Messenger.
        msg.replyTo = mReplyMessenger;

        try {
            mMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override public void onServiceDisconnected(ComponentName name) {

    }
};

注意信使: Messenger, 消息: Message, 拼写略有不同.

绑定服务

添加Connection, 使用Context.BIND_AUTO_CREATE, 绑定自动创建.

public void bindService(View view) {
    Intent intent = new Intent(this, MessengerService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

解绑服务unbindService.

public void unbindService(View view) {
    try {
        unbindService(mConnection);
        Toast.makeText(view.getContext(), "解绑成功", Toast.LENGTH_SHORT).show();
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(view.getContext(), "未绑定", Toast.LENGTH_SHORT).show();
    }
}

绑定服务一定需要解绑服务, 防止泄露. 如果没有注册, 解绑会发生异常.


服务端

服务端负责接收数据, 收到给客户端反馈.

MessengerService继承Service, 显示客户端消息msg.getData(). 反馈信息的Messenger使用客户端传递的, 创建消息添加内容, 使用客户端的Messenger传递给客户端.

处理与反馈数据

/**
 * 信使的持有, 处理返回信息
 */
private static class MessengerHandler extends Handler {
    private Context mContext;

    public MessengerHandler(Context context) {
        mContext = context.getApplicationContext();
    }

    @Override public void handleMessage(Message msg) {
        switch (msg.what) {
            case ParasConsts.MSG_FROM_CLIENT:

                // 收到消息
                String content = String.valueOf("服务端 - 收到消息: "
                        + msg.getData().getString(ParasConsts.MSG_ARG));
                Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show();

                // 回复消息
                Messenger client = msg.replyTo;
                Message reply = Message.obtain(null, ParasConsts.MSG_FROM_SERVICE);
                Bundle data = new Bundle();
                data.putString(ParasConsts.REPLY_ARG, "消息已经收到");
                reply.setData(data);

                // 发生Reply的信息
                try {
                    client.send(reply);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

                break;
            default:
                super.handleMessage(msg);
        }
    }
}

绑定接收数据

使用Handler创建服务端的Messenger

mMessenger = new Messenger(new MessengerHandler(getApplicationContext()));

绑定Handler, 与客户端交流.

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

默认返回null.


客户端, 使用Messenger传递消息Message, Message中添加序列化数据Bundle; 服务端, 使用Handler解析获取的Message, 通过辨别类型, 获取数据. Messenger使用非常明晰, 易于控制, 是简单进程通信的首选.

OK, that's all! Enjoy it!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容