android Handler详细使用方法实例

2023-11-04

开发环境为android4.1.

Handler使用例1
这个例子是最简单的介绍handler使用的,是将handler绑定到它所建立的线程中.
本次实验完成的功能是:单击Start按钮,程序会开始启动线程,并且线程程序完成后延时1s会继续启动该线程,每次线程的run函数中完成对界面输出nUpdateThread...文字,不停的运行下去,当单击End按钮时,该线程就会停止,如果继续单击Start,则文字又开始输出了。

软件界面如下:


实验主要部分代码和注释:

MainActivity.java:

复制代码代码如下:

package com.example.handler1;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView text_view = null;
    private Button start = null;
    private Button end = null;

    //使用handler时首先要创建一个handler
    Handler handler = new Handler();
    //要用handler来处理多线程可以使用runnable接口,这里先定义该接口
    //线程中运行该接口的run函数
    Runnable update_thread = new Runnable()
    {
        public void run()
        {
            //线程每次执行时输出"UpdateThread..."文字,且自动换行
            //textview的append功能和Qt中的append类似,不会覆盖前面
            //的内容,只是Qt中的append默认是自动换行模式
            text_view.append("\nUpdateThread...");
            //延时1s后又将线程加入到线程队列中
            handler.postDelayed(update_thread, 1000);

        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        text_view = (TextView)findViewById(R.id.text_view);
        start = (Button)findViewById(R.id.start);
        start.setOnClickListener(new StartClickListener());
        end = (Button)findViewById(R.id.end);
        end.setOnClickListener(new EndClickListener());

    }

    private class StartClickListener implements OnClickListener
    {
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //将线程接口立刻送到线程队列中
            handler.post(update_thread);
        }                
    }

    private class EndClickListener implements OnClickListener
    {

        public void onClick(View v) {
            // TODO Auto-generated method stub
            //将接口从线程队列中移除
            handler.removeCallbacks(update_thread);
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}



activity_main.xml:
复制代码代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/text_view"
        android:layout_width="fill_parent"
        android:layout_height="200dip"
        android:text="@string/hello_world"
        tools:context=".MainActivity" />
    <Button 
        android:id="@+id/start"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/start"
        />
    <Button 
        android:id="@+id/end"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/end"
        />

</LinearLayout>
 



Handler使用例2
这个例子比刚才那个例子稍微复杂些。因为这个例子中用到了handler的消息队列机制,即通过handler中一个线程向消息队列中用sendMessage方法发送消息,发送的消息当然可以用来传递参数。在handler中用handleMessage来处理消息,处理方法是获得消息队列中的消息参数,用这些参数来完成另外一些功能。
本实验实现的是当开始按钮按下时,会启动一个线程,并绑定到handler中,该线程发送带有参数的message到handler的消息队列中,消息队列的另一端获取该消息,并且用该消息的参数来更新进度条。

软件打开后:


单击Start按钮后,更新的进度条结果如下(怎么感觉4.1版本android进度条那么小呢?不懂该怎么设置):

实验主要部分代码和注释:
MainActivity.java:

复制代码代码如下:

package com.example.handler2;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends Activity {

    private ProgressBar progress_bar = null;
    private Button start = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        progress_bar = (ProgressBar)findViewById(R.id.progress_bar);
        start = (Button)findViewById(R.id.start);

        start.setOnClickListener(new StartOnClickListenr());
    }

    private class StartOnClickListenr implements OnClickListener
    {
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //让进度条显示出来
            progress_bar.setVisibility(View.VISIBLE);
            //将线程加入到handler的线程队列中
            update_progress_bar.post(update_thread);

        }
    }

    //创建一个handler,内部完成处理消息方法
    Handler update_progress_bar = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            //super.handleMessage(msg);
            //显示进度条
            progress_bar.setProgress(msg.arg1);
            //重新把进程加入到进程队列中
            update_progress_bar.post(update_thread);
        }       
    };//不加这个分号则不能自动添加代码

    Runnable update_thread = new Runnable()
    {
        int i = 0;
        public void run() {
            // TODO Auto-generated method stub
            i += 10;
            //首先获得一个消息结构
            Message msg = update_progress_bar.obtainMessage();
            //给消息结构的arg1参数赋值
            msg.arg1 = i;
            //延时1s,java中的try+catch用来排错处理
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO: handle exception
                e.printStackTrace();
            }
            //把消息发送到消息队列中
            update_progress_bar.sendMessage(msg);
            if(i == 100)
                //把线程从线程队列中移除
                update_progress_bar.removeCallbacks(update_thread);
        }       
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}



activity_main.xml:
复制代码代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button 
        android:id="@+id/start"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="@string/start"
        />
    <ProgressBar 
        android:id="@+id/progress_bar"
        android:layout_width="fill_parent"
        android:layout_height="100dip"
        android:layout_alignParentTop="true"
        style="?android:attr/progressBarStyleHorizontal"
        android:visibility="gone"
        />

</RelativeLayout>



Handler使用例3
上面2个例子表面上看handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程,因为它只是运行了线程的run方法,而不是start方法。Mars老师实验3的目的是为了验证仅使用handler的post方法是否处于同一个线程。
该实验在主activtiy的onCreate函数中打印了2条关于本线程的信息,然后创建一个handler并为它绑定一个线程,在线程的run方法中也打印了线程的信息,观察2者的信息是否一样。

结果如下:
说明这2个线程确实是同一线程,并且可以看出主界面中的文字大概过了10s才显示出来,因为语句setContentView(R.layout.activity_main);放在了handler的post启动语句后面,而handler绑定的线程中又延时了10s,所以同时也证明了只有是同一个线程才会出现这种情况。

程序主要代码和注释如下:

MainActivity.java:

复制代码代码如下:

package com.example.handler3;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;

public class MainActivity extends Activity {

    //新建一个handler
    private Handler handler = new Handler();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //将runnable加载到handler的线程队列中去
      //  handler.post(r);        
        Thread t = new Thread(r);
        t.start();
        setContentView(R.layout.activity_main);
        //打印activtiy线程信息
        System.out.println("activity_id---->"+Thread.currentThread().getId());
        System.out.println("activity_name---->"+Thread.currentThread().getName());
    }

    Runnable r = new Runnable()
    {
        public void run() {
            // TODO Auto-generated method stub
            //打印新建线程信息
            System.out.println("handler_id---->"+Thread.currentThread().getId());
            System.out.println("handler_name---->"+Thread.currentThread().getName());
            //延时10s,为了观察主界面中内容出现的时间
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }

    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}



如果把语句:
handler.post(r);
换成:
Thread t = new Thread(r);
t.start();
其它的不变,则程序运行时主界面内容立刻就显示出来了,且系统输出如下:
这2者都说明这样绑定的线程与它所在的activity线程就不是同一个线程了。

Handler使用例4
这个例子将学会怎样不使用runnable来启动一个线程,而是用HandlerThread的looper来构造一个handler,然后该handler自己获得消息,并传递数据,然后又自己处理消息,当然这是在另一个线程中完成的。
消息结构中传递简单的整型可以采用它的参数arg1和arg2,或者传递一些小的其它数据,可以用它的object,该object可以是任意的对象。当需要传送比较大的数据是,可以使用消息的setData方法,该方法需要传递一个Bundle的参数。Bundle中存放的是键值对的map,只是它的键值类型和数据类型比较固定而已。

程序主要代码和注释如下:
MainActivity.java:
复制代码代码如下:

package com.example.handler4;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        System.out.println("activity_ID---->"+Thread.currentThread().getId());
        //新建一个HanderThread对象,该对象实现了用Looper来处理消息队列的功能
        HandlerThread handler_thread = new HandlerThread("handler_thread");
        handler_thread.start();
        //MyHandler类是自己继承的一个类,这里采用hand_thread的Looper来初始化它
        MyHandler my_handler = new MyHandler(handler_thread.getLooper());
        //获得一个消息msg
        Message msg = my_handler.obtainMessage();

        //采用Bundle保存数据,Bundle中存放的是键值对的map,只是它的键值类型和数据类型比较固定而已
        Bundle b = new Bundle();
        b.putString("whether", "晴天");
        b.putInt("temperature", 34);
        msg.setData(b);
      //将msg发送到自己的handler中,这里指的是my_handler,调用该handler的HandleMessage方法来处理该mug
        msg.sendToTarget();
    }

    class MyHandler extends Handler
    {
        //空的构造函数
        public MyHandler()
        {}
        //以Looper类型参数传递的函数,Looper为消息泵,不断循环的从消息队列中得到消息并处理,因此
        //每个消息队列都有一个Looper,因为Looper是已经封装好了的消息队列和消息循环的类
        public MyHandler(Looper looper)
        {
            //调用父类的构造函数
            super(looper);
        }
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            System.out.println("Handler_ID---->"+Thread.currentThread().getId());
            System.out.println("Handler_Name---->"+Thread.currentThread().getId());
            //将消息中的bundle数据取出来
            Bundle b = msg.getData();
            String whether = b.getString("whether");
            int temperature = b.getInt("temperature");
            System.out.println("whether= "+whether+" ,temperature= "+temperature);
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}



总结:
Android中的handler可以用来完成异步的消息出来,即发送消息和接收消息相互独立,可以同时运行。在例1和例2中,实际上handler中使用的线程是与它所在的activity处于同一个主线程,因为handler中调用的runnable接口是直接运行该接口的run函数的,而不是start函数。例3专门比较了这2中情况。例4学会使用怎样在新线程中处理消息的方法。


from: http://www.jb51.net/article/43360.htm



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

android Handler详细使用方法实例 的相关文章

  • Win10 Snip & sketch无法保存截图

    如果你看到了我的博客 相信你也遇上了上面这个问题 在一次win10更新后发现 当按下Win Shift S使用截图后无法正常保存的问题 我寻找了很多文章也没有找到解决方案 最后找到了一个替代的软件 感觉挺好用的 微软官网上面找到的答案在 这
  • 【千律】C++基础:计算宽窄字节字符串所占用的字节数

    include
  • 【C ++ 】C++中的double和float区别

    文章目录 一 概述 二 精度的理解 三 存储空间 四 范围 五 运算精度 一 概述 在C 中 double和float是用于表示浮点数的两种数据类型 它们具有以下的详细介绍和区别 精度 double类型的变量具有更高的精度 即它可以表示更多
  • NPM详解

    NPM详解 介绍 命令 执行多个脚本 pre post 错误 静默消息 日志等级 从文件中引用路径 访问环境变量 传递参数 命名规则 前缀 在拿到一个项目之后 如何看入口文件 如何运行项目 我们都会找到 package json 中的 sc
  • 小点dian儿:pandas数据存入文件,行索引处理

    小点dian儿 存入数据的时候 我们希望对数据在系统的行名 保存或者不保存 参数 index None 类似 header False不保存列名 在我们不进行如上的设计的时候 系统或分配默认的行index 0 1 2 在我们将运行结果存入文
  • Python预测糖尿病

    今天给大家讲解一个实战案例 如何根据现有数据预测糖尿病 在这个案例开始之前 希望大家回忆一下大学里讲过的线性回归的知识 这是数据挖掘里非常重要的一部分知识 当然 鉴于大家都学过 本篇就不再赘述 一 数据集介绍 diabetes datase
  • 人工学习之预测2023年考研英语答案分布

    统计了2012 2022年共计11年的英语一完形和阅读答案 除了20年 ABCD四个选项基本都均匀分布 所以大概率是各自5个或者两个5一个4 20年类似13年 不管完形还是阅读 答案都是十分均匀分布 即5555型 至于原因 可能是老师的偏好
  • 计算机网络(第七版)谢希仁1-2章笔记

    笔记基于谢希仁老师的计算机网络笔记 第七版 第1 2章 1章 概述 2章 物理层 第1章 概述 1 1 计算机网络在信息时代的中的作用 1 21世纪的一些重要特征就是数字化 网络化和信息化 是一个以网络为核心的信息时代 2 三类网络 电信网
  • 登录功能的测试点大全

    登录功能的测试点大全 还是比较全面的 有什么考虑不到的 可以补上 功能性用例 1 输入已注册的用户名和正确的密码 验证是否成功登录 2 输入已注册的用户名和不正确的密码 验证是否成功失败 且提示信息正确 3 输入未注册的用户名和任意密码 验
  • [转]QNX_BSP包分析

    如果你认为本系列文章对你有所帮助 请大家有钱的捧个钱场 点击此处赞助 赞助额0 1元起步 多少随意 声明 本文只用于个人学习交流 若不慎造成侵权 请及时联系我 立即予以改正 锋影 email 174176320 qq com 这篇文章主要分
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • docker删除镜像和容器后,磁盘空间未释放

    用下列命令 docker container prune f docker image prune f docker volume prune f 它们将释放被停止容器 悬空图像和悬空卷使用的空间
  • 语雀 个人使用指南

    优点 markdown 此处为语雀内容卡片 点击链接查看 https www yuque com nanfang fw1qz wuc5c4 cts7ny 特色卡片 基础模块 思维导图无缝组成文本 第三方服务 免费即够用 多平台 云端存储 中
  • React学习笔记之十四: React hooks初探

    React Hooks 本文参考主要博文 阮一峰老师的 React hooks 教程 How to fetch data with React Hooks useEffect 完整指南 React hooks 的官方文档 demo Reac
  • git lfs的安装和使用

    20220304记录 lfs large file storage 安装 最新版本git lfs 3 0 2要求libc6 高于2 32 而Ubuntu20 04默认的libc6版本是2 31 不支持安装git lfs 3 0 2 因此Ub

随机推荐

  • 一.数组(5)645. 错误的集合(位运算的方法不会)

    集合 s 包含从 1 到 n 的整数 不幸的是 因为数据错误 导致集合里面某一个数字复制了成了集合里面的另外一个数字的值 导致集合 丢失了一个数字 并且 有一个数字重复 给定一个数组 nums 代表了集合 S 发生错误后的结果 请你找出重复
  • RISCV核设计与Chisel语言入门资料

    RISCV SOC设计与Chisel语言入门资料 关于项目的一点说明 Rocket核与Chisel语言 关于项目的一点说明 今年三月 我和舍友一起参加了第四届全国集成电路设计大赛 选择了RISCV挑战杯的子赛题二网址 自二月份开始着手做该项
  • 表单全选与取消全选

    分析 1 全选和取消全选 让下方所有复选框的checked属性 选中状态 跟随全选按钮 2 下方的所有复选框选中全选按钮才选中 其中一个不选中全选按钮都不选中 每次点击下面的某个复选框都要循环检查下方复选框是否都被选中 flag保存全选按钮
  • Java程序员应该具备的技能

    Java程序员的三个阶段 第一阶段 三年 我认为三年对于程序员来说是第一个门槛 这个阶段将会淘汰掉一批不适合写代码的人 这一阶段 我们走出校园 迈入社会 成为一名程序员 正式从书本上的内容迈向真正的企业级开发 我们知道如何团队协作 如何使用
  • linux 远程拷贝命令

    一 scp命令 远程拷贝文件 Linux scp命令用于linux之间进行复制文件 scp 是secure copy 的缩写 scp 是基于ssh登录来进行安全拷贝 补充知识 ssh进行登陆 ssh 用户名 IP地址 scp优势 当服务器的
  • request和requestScope的区别

    1 request对象通常用来接收从客户端通过表单提交过来的数据 然后在servlet或者action中用request getParameter 的方法获取获取参数内容 2 而requestScope通常是在servlet和action中
  • redis详解(一)—— 概述

    首先 分布式缓存框架 可以 看成是nosql的一种 1 什么是redis redis 是一个基于内存的高性能key value数据库 2 Reids的特点 Redis本质上是一个Key Value类型的内存数据库 很像memcached 整
  • 【前端面试

    1 数据类型 1 基本数据类型 Undefined Null Boolean Number String 还有在 ES6 中新增的 Symbol 类型 2 引用数据类型 对象 数组 函数 日期和正则等等 2 判断类型的方法 基本类型判断 t
  • 最新前端面试题整理

    前端技术 常见浏览器的内核分别是什么 IE浏览器 Trident 内核 Firefox浏览器 Gecko内核 Safari浏览器 Webkit内核 Opera浏览器 最初是Presto内核 后来是Webkit 现在是Blink内核 Chro
  • TypeScript中数组类型的定义

    TypeScript中数组类型的定义 现在我们可以定义一个最简单的数组类型 比如就是数字类型 那么就可以这么写 const numberArr 1 2 3 这时候你把鼠标放在numberArr上面可以看出 这个数组的类型就是 number
  • 【Linux】进程间通信

    文章目录 1 进程间通信基础 2 管道 2 1匿名管道 2 1 1匿名管道的原理 2 2匿名管道的特点 2 3匿名管道函数 2 3 1用例 2 3 2实现ps ajx grep bash指令 2 4匿名管道的特点 2 5管道的大小 2 6管
  • 项目管理计算-- PV、EV、AC、BAC、EAC、ETC等计算公式含义

    一 总浮动时间TF和自由浮动时间FF的差别 项目进度网络图 其中每个小方块里面的若干数字是啥意思呢 最早开始时间 ES 最早结束时间 EF 最迟开始时间 LS 最迟结束时间 LF TF Total Flow 总浮动时间 FF Free Fl
  • 史上最全的 Hexo 博客搭建配置完全指南

    欢迎到我的博客查看最新文章 https blog clouder im 本篇博客基于 Centos 7 x root 用户 最近利用 Hexo Github Pages 搭建了一个博客 总体来说比较满意 中间也踩了不少坑 于是将我的配置过程
  • LevelDB使用指南

    这篇文章是levelDB官方文档的译文 原文地址 LevelDB library documentation 这篇文章主要讲leveldb接口使用和注意事项 leveldb是一个持久型的key value数据库 key value可以是任意
  • Node.js 搭配 Socket.io 实现与客户端实时通信

    最近准备用react搭建node搭建一个大数据可视化平台 并且服务端利用到socket io 客户端利用到socket io client 这里总结下基本使用方式 安装 npm i express socket io socket io c
  • SQLi LABS Less-34

    第三十四关注入点为 单引号字符串型 注入类型为 报错注入 此关卡通过 代码WAF 将单引号 转义成 我们使用 编译 绕过WAF 先上结果 and updatexml 1 concat 0x7e substr select group con
  • Delphi多层开发方案比较

    以下转载自 http blog sina com cn s blog 53decb4101009a5m html type v5 one label rela nextarticle http blog csdn net SmallHand
  • 华为机试HJ60 查找组成一个偶数最接近的两个素数

    HJ60 查找组成一个偶数最接近的两个素数 Python 题目 解题思路 代码 结果 题目 解题思路 1 多组输入 需要循环 2 先创建一个判断是否素数的函数以备调用 素数判断 从1以后开始 如果到该数一半的位置有可以整除的数 则不是素数
  • 【pygame杂记】字体

    这一节放在这里挺突兀的 但是因为今天开周会 晚回来了 而且吃晚饭还吃撑了所以就简单写一下吧 举个栗子进行简述 我们知道在python中所有的东西都可以抽象成对象 在这里 我们创建了一个字体的对象 创建字体对象 font pygame fon
  • android Handler详细使用方法实例

    开发环境为android4 1 Handler使用例1 这个例子是最简单的介绍handler使用的 是将handler绑定到它所建立的线程中 本次实验完成的功能是 单击Start按钮 程序会开始启动线程 并且线程程序完成后延时1s会继续启动