Android Studio第14课——Android当中的Handler

1.Handler的基本概念

Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行出来,就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。 

2.Handler基本使用方法

1、创建一个Handler对象;
2、将要执行的操作卸载线程对象的run方法中;
3、将要执行的线程对象添加到队列当中;

3.Handler 常用方法:

post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你排列一个Runnable对象到主线程队列中, sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.


4.使用Handle小练习

1、打印数据
在Activity上添加两个按钮,分别是启动Handler和结束Handler
两个按钮的监听器方法如下:

    /**复写监听器点击时间方法*/
    class startButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            System.out.println("Start............");
            handler.post(updateThread);
        }
    }

    class endButtonListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            System.out.println("End............");
            handler.removeCallbacks(updateThread);
        }
    }
生成一个Handler类
Handler handler = new Handler();
添加一个updateThread线程:
    /**
     * 实现线程有两种方法
     * 1.继承Thread类
     * 2.实现Runnale接口*/
    Runnable updateThread = new Runnable() {
        @Override
        public void run() {
            System.out.println("UpdateThread");
            handler.postDelayed(updateThread,3000);
            /**
             * 当线程运行玩run方法之后,该线程就会进入死亡状态,
             * 所以在run方法里面添加运行本身线程的消息可以实现循环多次运行*/
        }
    };
updateThread线程里面很简单,进到updateThread线程run方法后先打印一串数据,然后调用 handler.postDelayed(updateThread,3000);等3s后继续把updateThread线程本身再加入到线程队列里面。
    

运行过程及结果:

1.当点击启动按钮后,进入到点击事件并实现里面的代码,先打印出来“Start............”,然后把UpdateThread线程加入到线程队列;

2.等该线程在线程队列里面被取出来的时候就会马上执行线程里面的run方法,此时会打印一次“UpdateThread”,然后执行3S后把UpdateThread加入到线程队列,run方法执行完毕,UpdateThread线程死亡。

3.3S时间到Handler会把UpdateThread线程重新加入到线程队列,依次循环...,所以打印窗口的现象时每隔3s会输出一次“UpdateThread”

4.当点击结束按钮时,先打印出“End............”,然后调用handler.removeCallbacks(updateThread)方法把UpdateThread线程从消息队列里面移除,所以Handler不会从线程队列里面取出该线程进而执行该线程里面的run方法。无法执行里面的run方法也就无法重新把UpdateThread线程重新加入到线程队列。结果就是结束了线程的循环调用。

需要注意:在点击完启动按钮之后,如果切换了Activity或者退出了当前的Activity,线程会依然在后台执行,再次进到这个Activity点击结束按钮后调用removeCallbaks并不能结束该线程。找了很多资料,都说再次进到Activity点击结束的UpdateThread线程并非正在运行的UpdateThread线程。解释:

在 Activity 由前台转后台过程中,线程是一直在运行的,但是当 Activity 转入前台时会重新定义 Runnable runnable;也就是说此时从message queue 移除的 runnable 与原先加入 message queue中的 runnable 并非是同一个对象。如果把 runnable 定义为静态的则removeCallbacks 不会失效,对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,在加载类的过程中完成静态变量的内存分配。


2、更新进度条ProgressBar
这里主要搞清楚两个概念:
1、线程队列
2、消息队列

线程队列和消息队列是两个独立的队列,遵循先进先出的原则,是一种异步关系,相互不干扰。

线程队列上面已经介绍的相对清楚,这里重点介绍消息队列,所谓的消息队列也是一个队列,所以就有发送消息和接收消息,或者称为加入消息和取出消息。
加入消息使用的方法就是Handler里面所用到发送消息的方法,如:handler.SendMessage(xxx);
通过此方法就会把一个消息加入到消息队列,当handler从消息队取出消息后会马上调用handler里面的一个匿名内部类方法  public void handleMessage(Message msg) ,而这个方法在定义的时候可以复写,里面的内容当然可以自己修改啦。


这里的测试就是把消息队列和线程队列都用上了,结合他们的特性去更新UI,贴上代码:

xxx.java部分

package com.example.urien.handler;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

public class HandlerProgressBarActivity extends AppCompatActivity {

    /**
     * 声明控件
     */
    ProgressBar progressBar;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_progress_bar);

        /**找到控件*/
        progressBar = findViewById(R.id.progressBar);
        button = findViewById(R.id.buttonProgressBar);

        /**设置监听器*/
        button.setOnClickListener(new buttonListener());

    }

    /**
     * 复写监听器方法
     */
    class buttonListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            /**设置进度条为可见状态*/
            progressBar.setVisibility(View.VISIBLE);
            progressBar.setMax(100);
            /**把UpdateThread线程加入线程队列*/
            System.out.println("Start UpdateThread!");
            handler.post(UpdateThread);
        }
    }

    Handler handler = new Handler() {
        @Override
        /**handler接收到UpdateProgressBar的SendMessage方法传递来的消息后
         * 当从消息队列里面取出消息时会执行此方法*/
        public void handleMessage(Message msg) {
            /**从传递过来的msg中得到arg1,并把这个值设置成当前的进度条*/
            progressBar.setProgress(msg.arg1);
            /**把UpdateThread线程加入线程队列*/
            handler.post(UpdateThread);
        }
    };

    Runnable UpdateThread = new Runnable() {

        int bar = 0;
        @Override
        public void run() {
            System.out.println("Run UpdateThread!");
            bar += 10;
            /**得到一个消息对象
             * 该消息对象由UpdateProgressBar的obtainMessage提供
             * */
            Message msg = handler.obtainMessage();
            msg.arg1 = bar;
            try{
                /**设置当前的线程睡眠1000ms*/
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if(bar == 100) {
                /**当进度条满后,停止UpdateThread线程*/
                System.out.println("End UpdateThread.......");
                progressBar.setVisibility(View.GONE);
                handler.removeCallbacks(UpdateThread);
            }
            else
                handler.sendMessage(msg);
        }
    };
}
xml部分
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <!--
    android:visibility="gone"设置成不可见
    -->
    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="fill_parent"
        android:layout_height="40dp"
        style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"
        android:visibility="gone"
        />
    <Button
        android:id="@+id/buttonProgressBar"
        android:layout_below="@+id/progressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="false"
        android:text="Start"
        />
</RelativeLayout>

By Urien 2018年6月24日 10:49:29

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值