1、Handler介绍

在Android开发中,我们常会使用单独的线程来完成某些操作,比如用一个线程来完成从网络上下的图片,然后显示在一个ImageView上,在多线程操作时,Android中必须保证以下两点:

(1)不要阻塞UI线程

(2)不要再UI线程之外访问Android UI工具包

有了以上两点的限制,我们在程序之间的消息如何进行传递呢?

用Handler,消息的处理者。

public class MainActivity extends Activity {private TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv = (TextView) findViewById(R.id.tv);}private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 100:tv.setText("下载完成");break;}}};public void downloadClick(View view) {//使用线程模拟下载操作new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}break;}handler.sendEmptyMessage(100);}}).start();}
}

2、Handler常用API

使用handler可以完成以下两点工作:

(1)消息调度和在将来的某个时间点执行一个Runnable

(2)多个任务加入到一个队列中执行

Handler相关方法:

                //发送一个空消息,即obj为空,标记为100handler.sendEmptyMessage(100);//获取一个消息对象,返回一个Msg对象Message msg = handler.obtainMessage();msg.what = 100;msg.obj = "要存的信息";//任意类型handler.sendMessage(msg);//发送消息//在制定时间后发送消息handler.sendEmptyMessageAtTime(200, System.currentTimeMillis() + 3000);//延迟2s后发送消息handler.sendEmptyMessageDelayed(300, 2000);

3、Handler内部实现原理

Handler实现机制:

(1)Message对象,表示要传递的一个消息

(2)MessageQueue对象,存放消息对象的消息队列,先进先出原则

(3)Looper对象负责管理当前线程的消息队列(MessageQueue)

(4)Handler对象负责把消息push到消息队列中,以及接收Looper从消息队列中取出的消息

Android启动程序时会在UI线程创建一个MessageQueue。

/*** Handler机制* 1、Message 消息对象,内部使用链表数据结构实现一个消息池,用于重复利用,避免大量创建消息对象,造成内存浪费* 2、Handler 消息处理者,通过该对象把消息存入消息队列,并最后通过HandlerMessage方法处理消息* 3、MessageQueue 消息队列,用于存储Message对象的数据结构,先进先出* 4、Looper 消息队列的处理者,用于循环检查消息队列,从消息队列中一个一个的取出消息对象,传入HandlerMessage方法*/

4、Handler内存泄露问题分析

内存泄漏:当activity退出后,handler依然还占用activity的引用,导致activity没有真正退出,依然占用内存。解决方法如下:

/*** Handler的内存泄露问题* 1、定义一个内部类时,会默认拥有外部类对象的引用,所以建议使用内部类时,最好定义为一个静态内部类* 2、引用的强弱,强引用->软引用 ->弱引用*/public class HandlerMemoryActivity extends Activity {private MyHandler handler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_handler_memory);//使用Handler延迟执行一个Runnable(10分钟)handler.postDelayed(new Runnable() {@Overridepublic void run() {System.out.println("!!!!!!run");}}, 1000 * 60 * 10);//关闭当前的Activity
        finish();}private static class MyHandler extends Handler {WeakReference<HandlerMemoryActivity> weakReference;public MyHandler(HandlerMemoryActivity activity) {weakReference = new WeakReference<HandlerMemoryActivity>(activity);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);HandlerMemoryActivity activity = weakReference.get();if (activity != null) {//做处理
            }}}
}

5、AsyncTask

除了使用Handler实现线程间的通信外,Android提供了一个工具类:AsyncTask,他使创建需要与用户界面交互的长时间运行的任务变得简单,相对来说AsyncTask更清凉已写,适用与简单的异步处理,不需要借助线程和Handler即可实现。

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

Params启动任务执行的输入参数,比如,Http请求的URL;

Progress后台任务执行的百分比

Result后台执行任务的最中返回结果,比如String

AsyncTask的执行步骤:

AsyncTask的执行分为四个步骤,每一步对应一个回调方法,我们需要的就是实现这些方法。

(1)首先定义一个类继承AsyncTask

(2)实现AsyncTask中定义的下面一个或几个方法

四个执行步骤分别为:

(1)onPreExecute():被UI Thread调用,该方法用来做已写准备工作,如在界面上显示一个进度条

(2)doInBackground(Params..):将在onPreExcute之后执行,运行在后台的线程中。负责执行耗时操作。可以调用publishProgress方法来更新实时任务进度

(3)onProgressUpdate(Progress..):在publishProgress方法被调用后,UI Thread将调用该方法在界面上展示任务的进展情况

(4)onPostExcute(Result):在doInBackground执行完成后,onPostExcute(Result)方法将被UI Thread调用,后台的计算结果将通过该方法传递到UI Thread。

AsyncTask准则:

(1)AsyncTask的实例必须在UI Thread中创建。

(2)excute方法必须在UI Thread中调用

(3)不要手动调用onPreExecute、onPostExecute、doInBackground和onProgressUpdate这借个方法

(4)改Task只能被执行一次,否则多次调用时会出现异常

(5)AsyncTask不能饿完全取代线程,在一些逻辑较为复杂或者后台反复执行的逻辑可能就需要线程来实现了

public class MainActivity extends Activity {private TextView tv;private ProgressBar progressBar;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv = (TextView) findViewById(R.id.tv);progressBar = (ProgressBar) findViewById(R.id.progressBar);}public void downloadClick(View view) {new MyAsyncTask(MainActivity.this).execute("http://a.hiphotos.baidu.com/image/pic/item/d50735fae6cd7b8926b326c20c2442a7d8330e97.jpg");}/*** 通过AsyncTask实现一个异步任务*/private static class MyAsyncTask extends AsyncTask<String, Integer, Integer> {private MainActivity activity;public MyAsyncTask(MainActivity activity) {this.activity = activity;}//执行任务之前触发的事件,可以在该方法中做一些初始化动作,例如显示一个dialog//这个是在主线程中
        @Overrideprotected void onPreExecute() {super.onPreExecute();activity.progressBar.setProgress(0);}//在子线程中//执行后台任务的方法
        @Overrideprotected Integer doInBackground(String... params) {String s = params[0];try {URL url = new URL(s);HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();//获取文件的大小int size = urlConnection.getContentLength();//0是一个标记,表示需要更新的最大进度值,1表示更新当下下载的进度值publishProgress(0, size);byte[] bytes = new byte[100];int len = -1;FileInputStream in = (FileInputStream) urlConnection.getInputStream();FileOutputStream out = new FileOutputStream("/sdcard/" + System.currentTimeMillis() + ".jpg");while ((len = in.read(bytes)) != -1) {out.write(bytes, 0, len);//更新进度publishProgress(1, len);out.flush();}out.close();in.close();} catch (Exception e) {e.printStackTrace();}return 200;}//更新进度
        @Overrideprotected void onProgressUpdate(Integer... values) {super.onProgressUpdate(values);switch (values[0]) {case 0:activity.progressBar.setMax(values[1]);break;case 1:activity.progressBar.incrementProgressBy(values[1]);break;}}@Overrideprotected void onPostExecute(Integer integer) {super.onPostExecute(integer);if (integer == 200) {activity.tv.setText("下载完成");}}}
}

转载于:https://www.cnblogs.com/chhom/p/4732041.html

Handler与多线程相关推荐

  1. android 多个handler,Android中的Handler与多线程应用实例

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

  2. Android之旅--Handler与多线程

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

  3. android 多线程 场景,精选Android初中级面试题 (三): 深探Handler,多线程,Bitmap

    码个蛋(codeegg) 第 930 次推文 作者:Focusing 链接:https://juejin.im/post/5c85cead5188257c6703af47 Handler 1.谈谈消息 ...

  4. Android开发中的Handler和多线程

    在Android开发中我们常常用到Handler这个类去处理消息队列中的消息,以下这个例子实现的是利用Handler传递一个消息给线程,线程运行run()方法去更新进度条的进度,以下是源代码: pub ...

  5. 10_Android中通过HttpUrlConnection访问网络,Handler和多线程使用,读取网络html代码并显示在界面上,ScrollView组件的使用

     编写如下项目: 2 编写Android清单文件 <?xml version="1.0" encoding="utf-8"?> <mani ...

  6. Android多线程:深入分析 Handler机制源码(二)

    前言 在Android开发的多线程应用场景中,Handler机制十分常用 接下来,深入分析 Handler机制的源码,希望加深理解 目录 1. Handler 机制简介 定义 一套 Android 消 ...

  7. Android多线程源码学习笔记一:handler、looper、message、messageQueue

    最近在学习Android多线程相关知识的源码,现在把自己的笔记整理一下,写出来加深印象. Android多线程通讯的核心是handler.looper.message.messageQueue,这篇文 ...

  8. Android中的Handler

    当我们在处理下载或是其它须要长时间运行的任务时.假设直接把处理函数放在Activity的OnCreate或是OnStart中.会导致运行过程中整个Activity无响应,假设时间过长,程序就会挂掉. ...

  9. Android Handler详细使用方法实例

    ( 这个github 中是 HandlerThread 的一个用法,和本文的HanderThread写法不同 https://github.com/whtchl/HandlerThread) 本文 ...

最新文章

  1. 朋友圈装死,微博蹦迪,Python教你如何掌握女神情绪变化 | CSDN博文精选
  2. 微信小程序input批量赋值(setData)
  3. Backbone与服务器接口之Model数据同步
  4. SLAM算法总结——经典SLAM算法框架总结
  5. 对搜狗输入法的个人评价
  6. hdu 3812 Sea Sky 深搜+剪枝
  7. 夏日防晒护肤经验心得与大家分享 - 生活至上,美容至尚!
  8. bondat蠕虫传播与对抗
  9. PureMVC在Unity游戏开发中的应用
  10. 2021年四川省政府工作报告:促进5G、大数据、区块链等技术与传统产业融合发展
  11. 【转载】制作Ubuntu启动盘——详细记录,亲测有效
  12. Reflex WMS中阶系列7:已经完成拣货尚未Load的HD如果要取消拣货,该如何处理?
  13. 写专业硕士论文,非功能性需求分析可套模板。
  14. JavaCV人脸识别三部曲之一:视频中的人脸保存为图片
  15. 中国大陆身份证号码有效性验证
  16. putty终端linux怎么粘贴复制,PuTTY下的保持SSH连接及复制粘贴功能
  17. Redis列表与集合
  18. 解决iPhone 浏览器上的圆角问题
  19. Android 应用的动画实践--View Animation篇
  20. 如何用Python批量导入Excel并用Pandas整合

热门文章

  1. DHL出台货运新方案
  2. java.util.prefs.Preferences
  3. es6 --- Promise.catch
  4. Vue项目代码改进(二)—— element-UI的消息显示时间修改
  5. AutoCAD.NET API 最新(2012)教程下载及在线视频教程DevTV
  6. UVa - 11988 Broken Keyboard(数组模拟链表)
  7. ShowMsg函数妙用
  8. [XMOVE自主设计的体感方案] XMove Studio管理系统(二)应用开发API简要介绍
  9. 主域控宕机无法恢复后,如何配置辅助域控继续工作
  10. Linux软件安装解决方案