多线程

一、为什么要使用多线程

1、提高用户体验或避免ANR

在事件处理代码中需要使用多线程,响应时间超过5s,即会出现ANR(Application is not responding),并因为响应较慢导致用户体验很差。

2、ANR详解

Android的main线程负责处理UI的绘制,为了防止应用程序反应较慢导致系统无法正常运行做如下处理:

  • 当用户输入事件(Activity)在5秒内无法得到响应,那么系统会弹出ANR对话框
  • BroadcastReciever 超过10秒没执行完也会弹出ANR对话

事件处理的原则:所有可能耗时的操作都放到其他线程去处理。

3、异步

应用中有些情况下并不一定需要同步阻塞去等待返回结果,可以通过多线程来实现异步

例如:某个Activity需要从云端获取一些图片,加载图片比较耗时,这时需要使用异步加载,加载完成一个图片刷新一个

4、主线程Activity与子线程

默认启动的第一个Activity成为主线程 由此Activity创建的线程(子线程)无法对主线程控制的内容进行修改 只有UI线程才能更新UI

二、Handler线程通信

1、怎样解决跨线程更新UI呢???

方式1:其他线程委托UI线程更新UI 方式2:通过Handler发送Message给UI线程,令UI线程根据Message消息更新UI 方式3:使用Android提供的AsyncTask

1. 其他线程委托UI线程更新UI (此种方式最简单,只适用较简单的情况!)
 Activity.runOnThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable,long)
2. Handler线程间通讯
 >1、 Handler在android里负责发送和处理消息,通过它可以实现其他线程与Main线程之间的消息通讯。
>2、Looper负责管理线程的消息队列和消息循环。
>3、Message是线程间通讯的消息载体。两个码头之间运输货物,Message充当集装箱的功能,里面可以存放任何你想要传递的消息。
>4、MessageQueue是消息队列,先进先出,它的作用是保存有待线程处理的消息。
3、Message:

通过obtain获取Message对象,利用Android的内存回收机制,提高效率.        Message msg = Message.obtain();    或 Message msg=hanler.obtainMessage();

4、Message传递大量数据:

若线程间通讯的数据比较复杂,比如需要使用键值对来存放大量数据,此时需要使用setData()和getData()方法,用Bundle对象来封装数据,封装好后,使用Handler对象将此Message发送出去.

    Message msg = Message.obtain();
msg.what = 101;
Bundle bundle = new Bundle();
bundle.putInt("number",12);
bundle.putString("Name","Rice");
bundle.putString("Hobby","Swimming");
msg.setData(bundle);
5、Handler:
两个主要用途:
  1. 将Message或Runnable对象发送给其他线程
  2. 处理来自其他线程的Message.
主要方法:

1、发送Message:sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long) 2、处理Message:handleMessage(Message)

6、Handler Post方法

在Handler中,关于Post方式的方法有:

  1. boolean post(Runnable r):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,立即执行。
  2. boolean postAtTime(Runnable r,long uptimeMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,在特定的时间执行。
  3. boolean postDelayed(Runnable r,long delayMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,延迟delayMills秒执行
  4. void removeCallbacks(Runnable r):从消息队列中移除一个Runnable对象。
7、Handler Message方法

在Handler中,与Message发送消息相关的方法有:

1. Message obtainMessage():获取一个Message对象。
2. boolean sendMessage():发送一个Message对象到消息队列中,并在UI线程取到消息后,立即执行。
3. boolean sendMessageDelayed():发送一个Message对象到消息队列中,在UI线程取到消息后,延迟执行。
4. boolean sendEmptyMessage(int what):发送一个空的Message对象到队列中,并在UI线程取到消息后,立即执行。
5. void removeMessage():从消息队列中移除一个未响应的消息
6. boolean sendEmptyMessageDelayed(int what,long delayMillis):发送一个空Message到消息队列中,延迟执行。

8、Thread+Handler 缺陷

  • 线程的开销较大,如果每个任务都要创建一个线程,那么程序的效率要低很多。
  • 线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。
  • 另外,在新线程中更新UI还必须要引入handler,这让代码看上去非常臃肿。

三、AsyncTask异步任务

1、AsyncTask

  • AsyncTask的特点是任务在主UI线程之外运行,而回调方法是在主UI线程中,这就有效地避免了使用Handler带来的麻烦。
  • AsyncTask定义了三种泛型类型                                
    1. Params 启动任务执行的输入参数。
    2. Progress 后台任务执行的百分比。
    3. Result 后台执行任务返回的结果。

2、使用AsyncTask简化多线程开发

  • AsyncTask专门用于完成非UI线程更新UI的任务
  • 本质上也是开启新线程执行耗时操作,然后将结果发送给UI线程
  • 优点:简化代码,减少编写线程间通信代码这一繁琐且易出错的过程
  • 要点:

    1.  AsyncTask为抽象类,必须先子类化
    2. onPreExecute():开始执行前的准备工作
    3. doInBackground(Params ...):开始执行后台处理,并调用publishProgress(Progress )方法来更新实时的任务进度
    4. onProgressUpdate(Progress ...):在publishProgress()方法被调用后,UI线程将调用这个方法从而在界面上展示任务的进展情况
    5. onPostExecute(Result):执行完成后的操作,传送结果给UI线程

3、要遵守的准则:

  • Task的实例必须在UI 线程中创建
  • execute方法必须在UI 线程中调用
  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法,需要在UI线程中实例化这个task来调用。
  • 该task只能被执行一次,否则多次调用时将会出现异常
  • doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第三个为  doInBackground返回和onPostExecute传入的参数。

4、构造参数解读

  • private class task extends AsyncTask<String, String, String>
  • AsyncTask<>的参数类型由用户设定,这里设为三个String
  • 第一个String代表输入到任务的参数类型,也即是doInBackground()的参数类型,调用execute()方法时传入的参数类型
  • 第二个String代表处理过程中的参数类型,也就是doInBackground()执行过程中的产出参数类型,通过publishProgress()发消息,传递给onProgressUpdate()一般用来更新界面
  • 第三个String代表任务结束的产出类型,也就是doInBackground()的返回值类型,和onPostExecute()的参数类型

Android 线程_笔记的更多相关文章

  1. Android 服务_笔记

    Service服务 服务(Service)是Android中的四大组件之一,适用于开发无界面.长时间运行的应用功能,服务是在后台运行,服务的创建与Activity类似,只需要继承Service和在An ...

  2. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  3. Android系统--输入系统(八)Reader线程_使用EventHub读取事件

    Android系统--输入系统(八)Reader线程_使用EventHub读取事件 1. Reader线程工作流程 获得事件 size_t count = mEventHub->getEvent ...

  4. Android系统--输入系统(九)Reader线程_核心类及配置文件

    Android系统--输入系统(九)Reader线程_核心类及配置文件 1. Reader线程核心类--EventHub 1.1 Reader线程核心结构体 实例化对象:mEventHub--表示多个 ...

  5. Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析

    Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析 0. 前言 个人认为该知识点阅读Android源代码会不仅容易走进死胡同,并且效果并不好,前脚看完后脚忘记,故进行总结, ...

  6. Android系统--输入系统(十一)Reader线程_简单处理

    Android系统--输入系统(十一)Reader线程_简单处理 1. 引入 Reader线程主要负责三件事情 获得输入事件 简单处理 上传给Dispatch线程 InputReader.cpp vo ...

  7. Android系统--输入系统(十二)Dispatch线程_总体框架

    Android系统--输入系统(十二)Dispatch线程_总体框架 1. Dispatch线程框架 我们知道Dispatch线程是分发之意,那么便可以引入两个问题:1. 发什么;2. 发给谁.这两个 ...

  8. Android系统--输入系统(十七)Dispatcher线程_分发dispatch

    Android系统--输入系统(十七)Dispatcher线程_分发dispatch 1. 回顾 InputRead线程从输入设备当中得到输入事件 对于读到输入事件稍作处理,比如紧急事件,来电时候按下 ...

  9. Android(java)学习笔记211:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

随机推荐

  1. 将IDEA maven项目中src源代码下的xml等资源文件编译进classes文件夹

    如果使用的是Eclipse,Eclipse的src目录下的xml等资源文件在编译的时候会自动打包进输出到classes文件夹.Hibernate和Spring有时会将配置文件放置在src目录下,编译后 ...

  2. linux使用freetds 连接连远程服务器sqlservser2012

    1.下载:freetds-patched.tar.gz  http://www.freetds.org/software.html http://www.freetds.org/userguide/c ...

  3. Android破解学习之路(四)——Android游戏 3D摩托飞车破解

    经过前面三期的破解,想必大家已经非常熟悉破解的流程,这一篇也算是练手项目,我们继续来练习吧 apk下载地址:链接: https://pan.baidu.com/s/1sl3b3R3 密码: 6666 ...

  4. ES6之Class

    ES6中的Class和JS的比起来无疑是让对象原型的写法更加清晰,更像面向对象编程的语法而已,注意一个问题ES6里面的Class的内部定义的所有方法都是不可枚举的,而且在ES6中Class不存在变量提 ...

  5. iOS 轮播中遇到的问题(暂停、重新启动)

    一. 轮播的优化或者用Collection来实现 二.Timer  问题 我们可以这样来使用一个Timer [NSTimer scheduledTimerWithTimeInterval:1.0 ta ...

  6. Pytorch windows10安装教程

    强烈建议安装anaconda之后再来安装这个pytorch,具体怎么安装百度搜索就知道了. 温馨提示,在安装anaconda的时候记得将"添加到环境变量"(安装的时候是英文的)这一 ...

  7. MySQL 如何存储长度较大的varchar与blob

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/96 最近,在工作中遇到了MySQL中如何存储长度较长的字段类型问 ...

  8. Xamarin android CardView的使用详解

    android 5.0新增加的一个控件CardView,在support v7兼容包中,意思就是卡片View,虽然可以设置阴影,圆角等等样式,但是我们也可以自己写出来,谷歌工程师之所以出这个,肯定是帮 ...

  9. Xamarin Android Fragment的两种加载方式

    android Fragment的重点: 3.0版本后引入,即minSdk要大于11 Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套的Fra ...

  10. ArcGIS API for JavaScript 4.2学习笔记[14] 弹窗的位置、为弹窗添加元素

    这一节我们来看看弹窗的位置和弹窗上能放什么. 先一句话总结: 位置:可以随便(点击时出现或者一直固定在某个位置),也可以指定位置 能放什么:四种,文字.媒体(图片等).表格.附件. [Part I 位 ...