我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android中AsyncTask与handler用法实例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android中AsyncTask与handler用法实例分析

本文实例讲述了Android中AsyncTask与handler用法。分享给大家供大家参考,具体如下:

首先,我们得明确下一个概念,什么是UI线程。顾名思义,ui线程就是管理着用户界面的那个线程!

android的ui线程操作并不是安全的,并且和用户直接进行界面交互的操作都必须在ui线程中进行才可以。这种模式叫做单线程模式。

我们在单线程模式下编程一定要注意:不要阻塞ui线程、确保只在ui线程中访问ui组件

当我们要执行一个复杂耗时的算法并且最终要将计算结果反映到ui上时,我们会发现,我们根本没办法同时保证上面的两点要求;我们肯定会想到开启一个新的线程,让这个复杂耗时的任务到后台去执行,但是执行完毕了呢?我们发现,我们无法再与ui进行交互了。
为了解决这种情况,android为我们提供了很多办法。

1)、handler和message机制:通过显示的抛出、捕获消息与ui进行交互;

2)、Activity.runOnUiThread(Runnable):如果当前线程为ui线程,则立即执行;否则,将参数中的线程操作放入到ui线程的事件队列中,等待执行。

3)、View.post(Runnable):将操作放入到message队列中,如果放入成功,该操作将会在ui线程中执行,并返回true,否则返回false

4)、View.postDelayed(Runnable, long)跟第三条基本一样,只不过添加了一个延迟时间。

5)、android1.5以后为我们提供了一个工具类来搞定这个问题AsyncTask.

AsyncTask是抽象类,定义了三种泛型类型 Params,Progress,Result。

Params 启动任务执行的输入参数,比如HTTP请求的URL
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String

用程序调用,开发者需要做的就是实现这些方法。

1) 子类化AsyncTask
2) 实现AsyncTask中定义的下面一个或几个方法

onPreExecute(),该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
doInBackground(Params…),将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress…),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result),在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.

为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常


package cn.com.chenzheng_java; 
import android.os.AsyncTask; 
 
public class MyAsyncTask extends AsyncTask<String, Integer, Object> { 
  
 @Override 
 protected void onPreExecute() { 
 super.onPreExecute(); 
 } 
  
 @Override 
 protected Object doInBackground(String... params) { 
 return null; 
 } 
  
 @Override 
 protected void onProgressUpdate(Integer... values) { 
 super.onProgressUpdate(values); 
 } 
  
 @Override 
 protected void onPostExecute(Object result) { 
 super.onPostExecute(result); 
 } 
}

下面介绍最本质的多线程:hanlder和message机制:

为何需要多线程:

在日常应用中,我们通常需要处理一些“后台,用户不可见”的操作,例如说,我们需要下载一个音乐,要是你的应用必须等用户下载完成之后才可以进行别的操作,那肯定让用户非常的不爽。这时候,我们通常的做法是,让这些操作去后台执行,然后等后台执行完毕之后,再给用户弹出相应的提示信息。这时候,我们就需要使用多线程机制,然后通过创建一个新的线程来执行这些操作。

明白了,实现需求,我们就准备着手实现了。但是,经过进一步的了解,我们悲剧的发现,android中的线程机制是,只能在UI线程中和用户进行交互。当我们创建了一个新线程,执行了一些后台操作,执行完成之后,我们想要给用户弹出对话框以确认,但是却悲剧的发现,我们根本无法返回UI主线程了。(UI线程就是你当前看到的这些交互界面所属的线程)。

这时候,我们如果想要实现这些功能,我们就需要一个android为我们提供的handler和message机制。

先讲解下编程机制:

我们通常在UI线程中创建一个handler,handler相当于一个处理器,它主要负责处理和绑定到该handler的线程中的message。每一个handler都必须关联一个looper,并且两者是一一对应的,注意,这点很重要哦!此外,looper负责从其内部的messageQueue中拿出一个个的message给handler进行处理。因为我们这里handler是在UI线程中实现的,所以经过这么一个handler、message机制,我们就可以回到UI线程中了。

handler:处理后台进程返回数据的工作人员。
message:后台进程返回的数据,里面可以存储bundle等数据格式
messageQueue:是线程对应looper的一部分,负责存储从后台进程中抛回的和当前handler绑定的message,是一个队列。
looper:looper相当于一个messageQueue的管理人员,它会不停的循环的遍历队列,然后将符合条件的message一个个的拿出来交给handler进行处理。

注意,handler是在UI线程中声明的,如果我们直接用类似代码执行一个线程的话,实际上并没有创建一个新的线程,因为handler已经跟默认的UI线程中的looper绑定了。

如果有兴趣的话,可以去看下Handler的默认空构造函数便知道原因了,里面直接绑定了当前UI线程的looper。

下面给出一个比较简单,并且实用的实例。


public class MainActivity extends Activity implements OnClickListener { 
  private Button btnTXT; 
  private TextView tvTXT; 
  private StringBuffer returnMsg; 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    btnTXT = (Button)findViewById(R.id.btnTXT); 
    tvTXT = (TextView)findViewById(R.id.tvTXT); 
    btnTXT.setOnClickListener(this);     
  } 
  @Override 
  public void onClick(View v) { 
    returnMsg = new StringBuffer(); 
    // 创建一个包含Looper的线程,这里如果没有HandlerThread的调用,会直接将后边的MyRunnable放到UI线程队列(myHandler.post(new MyRunnable())) 
    HandlerThread handlerThread = new HandlerThread("handler_thread"); 
    handlerThread.start();   // 启动自定义处理线程 
    myHandler = new MyHandler(handlerThread.getLooper());    // 将handler绑定到新线程  
    myHandler.post(new MyRunnable());    // 在新线程中执行任务  
  } 
   
  Handler mainHanlder = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) { 
      if(msg.what == 0) { 
        tvTXT.setText(returnMsg.toString());  // 与主线程控件打交道(直接访问) 
      } 
    } 
  }; 
   
  private MyHandler myHandler = null; 
  private class MyHandler extends Handler{ 
      
    public MyHandler(){ 
      super(); 
    } 
     
    public MyHandler(Looper looper) { 
      super(looper); 
    } 
    // 处理具体的message消息,继承自父类的方法 
    @Override 
    public void handleMessage(Message msg) { 
      int what = msg.what;   
      Bundle bundle = (Bundle)msg.obj;      // 提取bundle中的信息 
      String name = bundle.getString("name"); 
      String sex = bundle.getString("sex"); 
      boolean marry = bundle.getBoolean("marray"); 
      int age = bundle.getInt("age"); 
      StringBuffer strBuf = new StringBuffer();    // 拼接bundle信息 
      strBuf.append("what = ").append(what).append("\n\n"); 
      strBuf.append("name = ").append(name).append("\n"); 
      strBuf.append("sex = ").append(sex).append("\n"); 
      strBuf.append("marry = ").append(marry).append("\n"); 
      strBuf.append("age = ").append(age).append("\n\n"); 
      strBuf.append("http://blog.csdn.net/sunboy_2050"); 
      returnMsg = returnMsg.append(strBuf);  // 保存要显示的结果 
      mainHanlder.sendEmptyMessage(0);    // 向主线程mainHanlder发送消息,与UI控件交互显示结果 
      super.handleMessage(msg); 
    } 
  } 
  // 构造Runnable,处理后台业务逻辑,如下载 
  private class MyRunnable implements Runnable{ 
    @Override 
    public void run() { 
      try { 
        Message msg = Message.obtain(myHandler);  // 捕获myHandler消息
        msg.what = 10; 
        Bundle bundle = new Bundle();        // 封装bundle信息 
        bundle.putString("name", "yanggang"); 
        bundle.putString("sex", "pure boy"); 
        bundle.putBoolean("marry", false); 
        bundle.putInt("age", 18); 
        msg.obj = bundle; 
        long thID = Thread.currentThread().getId(); 
        returnMsg.append(thID).append(" : send msg start...").append("\n"); 
        msg.sendToTarget();   // 向myHandler发送消息 
        Thread.sleep(3000); 
      } catch (Exception e) { 
        Log.i("", "Runnable send msg error..."); 
        e.printStackTrace(); 
      } 
    } 
  } 
}

运行结果:

完整实例代码代码点击此处本站下载。

希望本文所述对大家Android程序设计有所帮助。

您可能感兴趣的文章:Android开发笔记之:AsyncTask的应用详解android异步任务设计思详解(AsyncTask)Android开发笔记之:深入理解多线程AsyncTaskandroid教程之使用asynctask在后台运行耗时任务Android的异步任务AsyncTask详解Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)Android中AsyncTask的用法实例分享Android AsyncTask的缺陷和问题总结


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android中AsyncTask与handler用法实例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android中AsyncTask与handler用法实例分析

本文实例讲述了Android中AsyncTask与handler用法。分享给大家供大家参考,具体如下: 首先,我们得明确下一个概念,什么是UI线程。顾名思义,ui线程就是管理着用户界面的那个线程! android的ui线程操作并不是安全的,
2022-06-06

Android中AsyncTask的用法实例分享

* AsyncTask 看上去修改后的connect()方法已经可用了,但是这种匿名线程的方式是存在缺陷的:第一,线程的开销较大,如果每个任务都要创建一个线程,那么应用 程序的效率要低很多;第二,线程无法管理,匿名线程创建
2022-06-06

Android编程中Handler原理及用法实例分析

本文实例讲述了Android编程中Handler用法。分享给大家供大家参考,具体如下: 在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化。有关Handler的作用,我们总结为:与其他线程协同工作,接收其他
2022-06-06

android中AsyncTask类的示例分析

这篇文章将为大家详细讲解有关android中AsyncTask类的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。AsyncTask也叫做“异步任务”,是一个抽象类 AsyncTask约定了在子
2023-05-30

Android Handler 原理分析及实例代码

Android Handler 原理分析 Handler一个让无数android开发者头疼的东西,希望我今天这边文章能为您彻底根治这个问题 今天就为大家详细剖析下Handler的原理 Handler使用的原因1.多线程更新Ui会导致UI界面
2022-06-06

Android AsyncTask用法巧用实例代码

Android AsyncTask 联系人导入new AsyncTask, Integer, ArrayList>() {@Overrideprotected void
2022-06-06

Android中的Handler与多线程应用实例

本文首先解释一下handler是用来干嘛的,然后通过例子介绍其在多线程中的应用。 什么是Handler handler通俗一点讲就是用来在各个进程之间发送数据的处理对象。在任何进程中,只要获得了另一个进程的handler则可以通过handl
2022-06-06

Android中ListView用法实例分析

本文实例分析了Android中ListView用法。分享给大家供大家参考,具体如下: 通过在Layout中添加ListView Widget可以达到在页面布局具有列表效果的交互页面。在这里通过举例来说明怎样在Layout中添加ListVie
2022-06-06

Android中Bitmap用法实例分析

本文实例讲述了Android中Bitmap用法。分享给大家供大家参考,具体如下: 一般在android程序中把图片文件放在res/drawable目录下就可以通过R.drawable.id来使用,但在存储卡中的图片怎样引用呢?下面通过实现这
2022-06-06

Android中ImageView用法实例分析

本文实例分析了Android中ImageView用法。分享给大家供大家参考,具体如下: 猜牌游戏大家可能以前都玩过,这里我们用这个小游戏来说明ImageView的用法。 首先,在res/drawable中引入三张牌:分别是梅花7,梅花8,梅
2022-06-06

Android中WebView用法实例分析

本文实例讲述了Android中WebView用法。分享给大家供大家参考,具体如下: WebView相当于一个迷你浏览器,采用WebKit内核,因此完美支持html,javascript,css等。 在开发过程中应该注意几点: 1.Andro
2022-06-06

Android中ListActivity用法实例分析

本文实例分析了Android中ListActivity用法。分享给大家供大家参考,具体如下: 程序如下:import android.app.ListActivity; import android.os.Bundle; import an
2022-06-06

Android中AlertDialog用法实例分析

本文实例分析了Android中AlertDialog用法,分享给大家供大家参考,具体如下: Android中AlertDialog为一些程序提供了对话框,有些功能能够进一步满足程序的需要。下面举例介绍。 程序如下:import androi
2022-06-06

Android中Matrix用法实例分析

本文实例讲述了Android中Matrix用法。分享给大家供大家参考,具体如下: Matrix ,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。 首先介绍一下矩阵运算。加法和减法就不用说了,对应位相
2022-06-06

android Handler详细使用方法实例

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

Android ViewFlipper用法实例分析

本文实例讲述了Android ViewFlipper用法。分享给大家供大家参考,具体如下: 这里实现的效果是当手动滑动手机屏幕时会一个一个地显示图片,一次显示一张图片package com.my.viewflippertest; impor
2022-06-06

Android中SeekBar和RatingBar用法实例分析

本文实例讲述了Android中SeekBar和RatingBar用法。分享给大家供大家参考,具体如下: 什么是SeekBar? 可以拖动的进度条(在播放器中使用最常见) 1、在布局文件中声明
2022-06-06

Android控件之AnalogClock与DigitalClock用法实例分析

本文实例讲述了Android控件之AnalogClock与DigitalClock用法。分享给大家供大家参考。具体如下: 时钟控件包括AnalogClock和DigitalClock,它们都负责显示时钟,所不同的是AnalogClock控件
2022-06-06

Android开发中PopupWindow用法实例分析

本文实例分析了Android开发中PopupWindow用法。分享给大家供大家参考,具体如下:private TextView tv_appmanager_title; private ListView lv_app_manager; pr
2022-06-06

android中Handle类的用法实例分析

本文实例讲述了android中Handle类的用法。分享给大家供大家参考。具体如下: 当我们在处理下载或是其他需要长时间执行的任务时,如果直接把处理函数放Activity的OnCreate或是OnStart中,会导致执行过程中整个Activ
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录