Android Studio第15课——进一步认识Handler与线程

1、Handler与线程
在默认的情况下,使用Handler.post方法实际上和调用Handler的Activity是处于同一线程的。因为Handler是直接调用了run方法而并不是调用了线程的start方法。换句话说,线程是创建好了,但是并没有另外开启这个线程作为一个新的线程,而是在当前线程当中直接实现了该线程里面的run方法。这个可以通过Thread.currentThread().getId()和Thread.currentThread.getName()方法来获取当前线程的ID和名字来证实。结果是如果使用Handler来调用一个线程的run方法,那么线程里面获得的线程id和线程name与Activity或得到的线程id、线程name是一致的。


2、Bundle的用法

官方文档:A mapping from String values to various Parcelable types. 
Bundle类是一种数据载体,类似于Map,用于存放key-value名值对形式的值。可以把Bundle看成是一种特殊的map。一般的map里面的键和值都是object(任意类型)的,而Bundle是把键固定成string类型的,值可以是基本类型和基本类型数组等。

常用方法: 
putXxx()用于往Bundle对象放入数据, 
getXxx()用于从Bundle对象里获取数据。 
Bundle的内部实际上是使用了HashMap类型的变量来存放putXxx()方法放入的值。Bundle就是一个专门用于导入Intent传值的包。当然也可以在消息中使用。

3、在新线程当中处理消息的方法


1.Java标准启动一个线程方法

第一步、生成一个Handler对象
private Handler handler = new Handler();
第二步、定义一个Runnable类实现一个Runnable接口和里面的run方法
Runnable runnable = new Runnable() {
	@Override
	public void run() {
		System.out.println("handler-->" + Thread.currentThread().getId());
		System.out.println("handler-->" + Thread.currentThread().getName());
	}
};
第三步、生成一个Thread对象,并把生成的Runnable对象作为参数传入
Thread thread = new Thread(runnable);
第四步、调用Thread线程的start方法
thread.start();
当掉用完start方法后,线程进入就绪状态。

2.使用looper对象

Looper是由Android框架提供的一个类,主要作用是从队列里面取得消息。当队列里面有消息时就不断的从里面取出消息,没有消息时就进入空闲休眠状态。除了使用Looper外,Android还提供了一个HandlerThread类,这个类就实现了looper的取得消息的功能。所以一般使用HandlerThread类就可以了,很少去使用looper本身。

下面贴上Activity代码:

package com.example.urien.handler;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class Handler2Activity extends AppCompatActivity {


    private Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler2);
/**第一种方法创建线程
 Thread thread = new Thread(runnable);
 thread.start();
 System.out.println("activity-->" + Thread.currentThread().getId());
 System.out.println("activity-->" + Thread.currentThread().getName());
 */

        System.out.println("activity-->" + Thread.currentThread().getId());
        /**生成一个HandlerTherad对象,实现了使用Looper来处理消息队列的功能*/
        HandlerThread handlerThread = new HandlerThread("handler_thread");
        /**启动线程*/
        handlerThread.start();

        /**
         * 生成一个MyHandler对象
         * 并把HandlerThread使用getLooper得到的Looper对象作为参数传进去
         * 进而调用MyHandler类当中相应的构造函数
         * */
        MyHandler myHandler = new MyHandler(handlerThread.getLooper());

        /**通过Handler的obtainMessage方法来获取一个对应当前handler对象的消息对象*/
        Message message = myHandler.obtainMessage();


        /**s使用message里面的obj承载数据*/
        message.obj = "string";

        /**生成一个bundle对象存入不同类型的键值对*/
        Bundle bundle = new Bundle();
        bundle.putInt("test_int",12345);
        bundle.putString("test_string","test_string");


        /**使用message的setData方法存放数据*/
        message.setData(bundle);
        /**
         * 使用SendToTarget方法像Handler对象发送消息对象
         * 这里注意,这里的message.sendToTarget();中的message是对应的那个Handler
         * 就向那个Handler发送消息
         * 简单的说就是这个message对象是由那个handler生成的对应的Target就是那个Handler
         * */
        message.sendToTarget();
    }

    /**
     * 对应第一种方法创建线程
     * Runnable runnable = new Runnable() {
     *
     * @Override public void run() {
     * System.out.println("handler-->" + Thread.currentThread().getId());
     * System.out.println("handler-->" + Thread.currentThread().getName());
     * }
     * };
     */

    class MyHandler extends Handler {

        /**
         * 无参数的构造函数
         */
        public MyHandler() {

        }

        /**
         * 带有一个Looper对象作为参数的构造函数
         * 把looper作为参数的目的是把当前的Handler使用looper所在的线程去处理消息队列
         * 换句话说就是把当前的Handler绑定在另外一个Looper队列上去取得消息队列,进而处理消息
         */
        public MyHandler(Looper looper) {
            super(looper);//
        }

        /**
         * 每当向Handler发送一个消息对象的时候就会执行此方法
         */
        @Override
        public void handleMessage(Message msg) {
            /**得到message里面的string类型的消息数据*/
            String string = (String) msg.obj;

            /**得到Bundle里面传递过来的Bundle对象*/
            Bundle bundle = msg.getData();
            /**通过Bundle取得里面的数据*/
            int test_int = bundle.getInt("test_int");
            String test_string = bundle.getString("test_string");

            System.out.println("string-->" + string);
            System.out.println("text_int-->" + test_int);
            System.out.println("test_string-->" + test_string);
            System.out.println("handler-->" + Thread.currentThread().getId());
            System.out.println("handlerMessage");
        }
    }
}

代码注释的相对详细,不多解释。

顺带贴上第二种方法的测试结果:



By Urien 2018年6月25日 22:18:16


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值