android ipc机制之Messenger的使用

1.前面讲了关于ipc机制中的aidl的简单使用。最近看<<android艺术开发与探究>>里面涉及到Messenger的使用,为了加深印象,所以来此写一写。


2.Messenger英文单词的意思是"信使",它可以在不同的进程中传递Message对象。Messenger是轻量级的ipc方案,底层是aidl实现的。通过android api可以发现对于 Messenger类,它有俩个比较重要的构造法方法。


在这里我先把这俩个构造方法写出来,不先解释用法,后面再说。


3.现写一个Service服务,然后再声明一个handler对象,最后在声明一个Messenger对象。最后在onBind方法中返回Messenger.getBinder(). 具体代码如下:

package com.example.lenovo.myapplication;

/**
 * Created by lenovo on 20/6/2016.
 */
import android.app.Service;
import android.content.Intent;
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.util.Log;

/**
 * Created by lenovo on 20/6/2016.
 */
public class MyTestService extends Service {

    public static Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what)
            {
                case 1:
                    String value= (String) msg.getData().get("name");
                    Log.d("4577155",value);
                    Messenger messenger=msg.replyTo;
                    Bundle b=new Bundle();
                    b.putString("name","this is response");
                    Message message=Message.obtain(null,2);
                    message.setData(b);
                    try {
                        messenger.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                    break;
            }
            super.handleMessage(msg);
        }
    };
    public Messenger messenger=new Messenger(handler);
    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}

写好Service之后,在Mainfest文件里面配置Service,注意了:必须要加一个process属性。这个属性可以使该service在不同的进程中。

对Messenger messenger=new Messenger(handler);这段代码的解释:将handler与Messenger对象绑定在一起。在Messenger的对象可以调用一个send( Message mge)方法,跨进程发送一个Message对象,发送过来之后该消息由handler来处理。


4.服务端的service写好了。现在就是客户端的程序。客户端主要是启动该Service,通过”bindService 绑定式“ 来启动。关键要注意 的是重写ServiceConnection类的ServiceConnected()方法。具体代码如下:

package com.example.lenovo.myapplication;

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.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    Messenger messenger;


    public static Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what)
            {
                case 2:
                    String ss= (String) msg.getData().get("name");
                    Log.d("4577155",ss);
                    break;
            }

            super.handleMessage(msg);
        }
    };





    public Messenger mg=new Messenger(handler);
    public ServiceConnection con=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            messenger = new Messenger(service);
            Message m = Message.obtain(null, 1);
            Bundle bundle = new Bundle();
            bundle.putString("name", "wxy");
            m.replyTo=mg;
            m.setData(bundle);
            try {
                messenger.send(m);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    Button but1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        but1= (Button) findViewById(R.id.but1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setClass(MainActivity.this,MyTestService.class);
                bindService(intent,con, Context.BIND_AUTO_CREATE);
            }
        });
    }package com.example.lenovo.myapplication;

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.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    Messenger messenger;


    public static Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what)
            {
                case 2:
                    String ss= (String) msg.getData().get("name");
                    Log.d("4577155",ss);
                    break;
            }

            super.handleMessage(msg);
        }
    };





    public Messenger mg=new Messenger(handler);
    public ServiceConnection con=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
           <span style="background-color: rgb(255, 204, 255);"> messenger = new Messenger(service);
            Message m = Message.obtain(null, 1);
            Bundle bundle = new Bundle();
            bundle.putString("name", "wxy");</span>
            m.replyTo=mg;
         <span style="background-color: rgb(255, 204, 255);">   m.setData(bundle);</span>
            try {
             <span style="background-color: rgb(255, 204, 255);">   messenger.send(m);</span>
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    Button but1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        but1= (Button) findViewById(R.id.but1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setClass(MainActivity.this,MyTestService.class);
                bindService(intent,con, Context.BIND_AUTO_CREATE);
            }
        });
    }
}

}
上面代码中标记颜色的部分非常重要:正如前面贴的Messenger的构造方法,标记颜色的部分,第一部就是得到了Messenger对象。

然后在声明一个Message对象,设置好Data之后,然后调用Messenger.send(message)方法。将这个message发送到Service的进程中,被Service里面的handler处理。"m.replyto=......"这代码先不要管。

最后运行结果:



至于第二个打印下面再说:

下面先总结下:客户端和服务service在不同的进程中,客户端向服务端发送message。

1."绑定" Messenger,即 先声明一个Handler对象,然后通过Messenger(handler)这个构造方法获取到一个Messenger对象,然后再在onbind方法中 return  Messenger.getBinder();

2.客户端在ServiceConnection方法中,通过IBinder对象,获取到一个Messenger对象。这里我把Serice里面的Messenger和MainActivity里面的Messenger对象理解为同一个对象。原因就是:在Service的onbind方法中通过调用Messenger.getBinder(),返回一个Binder对象。在Activity的方法中又通过这个Binder,生成了一个Messenger对象,因此这个俩个类中的Messenger其实就是同一个对象。

3.每个Messenger对象必须和一个hander绑定。例如在A进程中声明了Messenger和handler。那么在B线程中必须调用Messenger.send(message);方法之后那么在handler里面才能接收到消息。注意A,B线程中的Messenger是同一个对象。




5.客户端发送消息到服务端我们知道了如何去做。那么服务端向客户端发送消息该如何去做呢?

那么这个时候,就不得不提message.replyto的方法了。服务端向客户端发送message,就是说接收方在MainActivity中,按照前面的总结我们要 声明一个Messenger 对象(在这里我们把Messenger称之为B对象)和一个handler对象,Messenger对象的构造方法,必须要调用Messenger(handler)这个方法,这样就将Messenger和handler绑定在一起了,接着只要在MyTestService类中,获取到MainActivity中的B对象,然后调用B的send(Message m)方法就可以实现服务端发送信息到客户端。

MyTestService的代码如下:

package com.example.lenovo.myapplication;

/**
 * Created by lenovo on 20/6/2016.
 */
import android.app.Service;
import android.content.Intent;
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.util.Log;

/**
 * Created by lenovo on 20/6/2016.
 */
public class MyTestService extends Service {

    public static Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what)
            {
                case 1:
                    String value= (String) msg.getData().get("name");
                    Log.d("4577155",value);
               <span style="background-color: rgb(204, 204, 255);">     Messenger messenger=msg.replyTo;
                    Bundle b=new Bundle();
                    b.putString("name","this is response");
                    Message message=Message.obtain(null,2);
                    message.setData(b);
                    try {
                        messenger.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }</span>
                    break;
            }
            super.handleMessage(msg);
        }
    };
    public Messenger messenger=new Messenger(handler);
    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}


着颜色那部分代码主要作用是:获取到从客户端传递过来的Messenger对象,也就是调用replyto方法。接着声明一个message,然后调用Messenger.send(message msg)方法将Message发送到MainActivity里面。

客户端也就是MainActivity方法中 ,新添加的代码主要是声明一个Handler和Messenger对象,只好把Messenger赋值给message.replyto.具体代码如下:

package com.example.lenovo.myapplication;

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.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    Messenger messenger;


   <span style="background-color: rgb(255, 204, 255);"> public static Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what)
            {
                case 2:
                    String ss= (String) msg.getData().get("name");
                    Log.d("4577155",ss);
                    break;
            }

            super.handleMessage(msg);
        }
    };





    public Messenger mg=new Messenger(handler);</span>
    public ServiceConnection con=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            messenger = new Messenger(service);
            Message m = Message.obtain(null, 1);
            Bundle bundle = new Bundle();
            bundle.putString("name", "wxy");
        <span style="background-color: rgb(255, 204, 255);">    m.replyTo=mg;</span>
            m.setData(bundle);
            try {
                messenger.send(m);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    Button but1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        but1= (Button) findViewById(R.id.but1);
        but1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setClass(MainActivity.this,MyTestService.class);
                bindService(intent,con, Context.BIND_AUTO_CREATE);
            }
        });
    }
}

标记颜色的为新添加的。最后运行结果



最后总结一下Messenger核心思想:

我理解的是将handler和Messenger绑定,其实也就是调用Messenger的new Messenger(handler )的构造方式,这个方法的其实就是把handler和Messenger绑定起来了。

然后将这个Messenger传递到其他的进程中,通过调研send(Message m)方法来发送一个消息。这样handler就可以处理那个message了。


今天就记录在这里。最近作者在看<<android开发艺术探究>>,将会记录下自己认为重要或者不熟悉的知识点。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值