Android--Handler+Looper+MessageQueue+Thread线程之间的通信

来源:互联网 发布:公司域名注册 编辑:程序博客网 时间:2024/05/29 17:12

几个关键概念:(参考网络相关博客)

1、MessageQueue:

  • 是一种数据结构,见名知义,就是一个消息队列,存放消息的地方;
  • 每一个线程最多只可以拥有一个MessageQueue数据结构;
  • 一个线程存在MessageQueue才能接收消息;
  • 通常使用一个Looper象对该线程的MessageQueue进行管理;
  • 主线程创建时,会创建一个默认的Looper对象和MessageQueue;
  • 其他非主线程,不会自动创建Looper,要需要的时候,通过调用prepare()函数来实现创建和某个线程关联的Looper,创建了关联的Looper就会自动创建一个MessageQueue。

2、Message:

  • 消息对象,Message Queue中的存放的对象; 一个Message Queue中包含多个Message;
  • Message实例对象的取得,通常使用Message类里的静态方法obtain(),该方法有多个重载版本可供选择;它的创建并不一定是直接创建一个新的实例,而是先从MessagePool(消息池)中看有没有可用的Message实例,存在则直接取出返回这个实例。如果MessagePool中没有可用的Message实例,则才用给定的参数创建一个Message对象。调用removeMessages()时,将Message从MessageQueue中删除,同时放入到Message Pool中;
  • 除了上面这种方式,也可以通过Handler对象的obtainMessage()获取一个Message实例。

3、Looper:

  • 是MessageQueue的管理者;
  • 每一个MessageQueue都不能脱离Looper而存在,Looper对象的创建是通过prepare函数来实现的;
  • 同时每一个Looper对象和一个线程关联;
  • 通过调用Looper.myLooper()可以获得当前线程的Looper对象;
  • 创建一个Looper对象时,会同时创建一个MessageQueue对象;
  • 除了主线程有默认的Looper,其他线程默认是没有MessageQueue对象的,所以,不能接受Message。如需要接受,自己定义一个Looper对象(通过Looper.prepare()函数),这样该线程就有了自己的Looper对象和MessageQueue数据结构了;
  • Looper从MessageQueue中取出Message然后,交由Handler的handleMessage进行处理;
  • 处理完成后,调用Message.recycle()将其放入Message Pool中。

4、Handler:

  • 消息的处理者,handler负责将需要传递的信息封装成Message,通过调用handler对象的obtainMessage()来实现;

  • 将消息传递给Looper,这是通过handler对象的sendMessage()来实现的;

  • 继而由Looper将Message放入MessageQueue中;

  • 当Looper对象看到MessageQueue中含有Message,就将其广播出去;该handler对象收到该消息后,调用相应的handler对象的handleMessage()方法对其进行处理。

具体代码如下所示:
主线程(UI线程)

package com.longshun.HandlerLooperHomework;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.view.View;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;//1.主线程,向子线程发消息;// 2.子线程接收主线程的消息,// 子线程根据主线程发过来的消息访问网络,得到数据后发送给主线程;public class MainActivity extends Activity {    //主线程有默认的Looper    private EditText txtUiMsg;    private TextView txtRes;    private Handler cHandler;    private ChildThread childThread;    //主线程要得到子线程的消息,先创建一个Handler    Handler fHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            int what = msg.what;            Object obj = msg.obj;            switch (what) {                case 0:                    txtRes.setText(obj.toString());//设置ui内容                    break;            }        }    };    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        txtUiMsg = (EditText) findViewById(R.id.txt_ui_msg);        txtRes = (TextView) findViewById(R.id.txt_return_msg);        //得到子线程任务对象,把主线程传给子线程,因为如果子线程要发消息给主线程,必须要有主线程的handler        childThread = new ChildThread(fHandler);        //启动子线程,子线程处于等待主线程发消息的状态        Thread thread = new Thread(childThread);        thread.start();    }    //点击按钮 主线程获取输入框内容 发送给子线程    public void btnSendMsg(View view) {        //获取输入框内容,去除前后空格        String UiMsg = String.valueOf(txtUiMsg.getText()).trim().replace(" ", "");        if (UiMsg != null && UiMsg.length() > 0) {            //得到与子线程关联的Handler,向子线程发消息            cHandler = childThread.getcHandler();            Message message = cHandler.obtainMessage(1);            message.obj = UiMsg;            cHandler.sendMessage(message);//发送消息给子线程            Toast.makeText(this, "send success and wait response!", Toast.LENGTH_SHORT).show();        } else {            Toast.makeText(this, "请输入你想对小黄鸡说的话!", Toast.LENGTH_SHORT).show();        }    }    @Override    protected void onDestroy() {        if (cHandler != null) {            cHandler.getLooper().quit();//得到和子线程相关的Looper,并且终止MessageQueue运行;        }        super.onDestroy();    }}

子线程:

package com.longshun.HandlerLooperHomework;import android.os.Handler;import android.os.Looper;import android.os.Message;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.json.JSONException;import org.json.JSONObject;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;/** * Created by LongShun on 2015/9/7. * Author:LongShun * Email:1261972397@qq.com *///子线程任务对象public class ChildThread implements Runnable {    private Handler cHandler;    private Handler fHandler;    //子线程要向主线程发消息,所以要得到与主线程绑定的fHandler,    // 通过这个fHandler才能给主线程发消息。    public ChildThread(Handler fHandler) {        this.fHandler = fHandler;    }    @Override    public void run() {        Looper.prepare();//!!!!!!!!创建一个和当前线程绑定的Looper,自动创建一个MessageQueue对象,        // !!!!!!!!!!!有了MessageQueue对象就能接收Message对象--消息        //和子线程绑定的cHandler,用来处理主线程发过来的消息。        //等待主线程发消息,有消息就处理,没消息就处于等待状态        cHandler = new Handler(){            @Override            public void handleMessage(Message msg) {                int what = msg.what;                switch (what){                    case 1:                        //1得到主线程发过来的消息                        String uiMsg = msg.obj.toString();                        //2根据消息,联网访问,得到结果                        String res = getResponse(uiMsg);                        //3.通过主线程fHandler ,把响应结果发送给主线程。                        Message message = fHandler.obtainMessage(0);                        message.obj = res;                        fHandler.sendMessage(message);                        break;                }            }        };        Looper.loop();//用于不断循环地从MessageQueue中取消息    }    //得到与子线程绑定的cHandler    public Handler getcHandler(){        return cHandler;    }    //解析json字符串    public String parserResult(String jsonString){        String result=null;        if (jsonString!=null){            try {                JSONObject jsonObject = new JSONObject(jsonString);                result = jsonObject.getString("res");            } catch (JSONException e) {                e.printStackTrace();            }        }        return result;    }    //联网获取json结果    private String getResponse(String uiMsg) {        //访问网络        String result = null;        if (uiMsg != null && uiMsg.length() > 0) {            String basePath = "http://www.simsimi.com/requestChat?lc=zh&ft=1.0&req=";            String path = basePath + uiMsg;            HttpGet get = new HttpGet(path);            HttpClient client = new DefaultHttpClient();            InputStream in = null;            ByteArrayOutputStream baos = null;            try {                HttpResponse response = client.execute(get);                if (response.getStatusLine().getStatusCode() == 200) {                    in = response.getEntity().getContent();                    baos = new ByteArrayOutputStream();                    byte[] b = new byte[1024];                    int len;                    while ((len = in.read(b)) != -1) {                        baos.write(b, 0, len);                    }                    result = parserResult(new String(baos.toByteArray(), "utf-8"));                }            } catch (IOException e) {                e.printStackTrace();            } finally {                if (baos != null) {                    try {                        baos.close();                    } catch (IOException e) {                        e.printStackTrace();                    }                }                if (in != null) {                    try {                        in.close();                    } catch (IOException e) {                        e.printStackTrace();                    }                }            }        }        return result;    }}

main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:orientation="vertical"              android:layout_width="fill_parent"              android:layout_height="fill_parent"        >    <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:orientation="vertical"            >        <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:textSize="28sp"                android:text="我问小黄鸡:"                />        <EditText                android:id="@+id/txt_ui_msg"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:textSize="28sp"                />    </LinearLayout>    <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:gravity="center"            >        <Button                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="主线程发送消息给子线程"                android:onClick="btnSendMsg"                />    </LinearLayout>    <LinearLayout            android:layout_width="match_parent"            android:layout_height="0dp"            android:layout_weight="1"            android:orientation="vertical"            >        <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:textSize="28sp"                android:text="小黄鸡回复:"                />        <TextView                android:id="@+id/txt_return_msg"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:textSize="28sp"                />    </LinearLayout></LinearLayout>
0 0
原创粉丝点击