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

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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值