Android中的Handler机制、异步任务

    xiaoxiao2021-03-25  69

    Android多线程Handler机制异步任务

    Android多线程

    一个Android的应用程序运行在一个独立的进程中,运行在一个独立的虚拟机(dvk)上。 (进程名为包名)

    Android应用程序开启后,默认开启一个主线程(UI线程)

    Activity,Service,BroadcastReceiver组件运行在主线程中

    Android应用程序退出后,保留空UI线程,可以加快应用程序启动速度

    用户不能在UI主线程中做耗时的操作,一旦该操作超过5s,应用程序抛一个ANR异常(Application not respond)。

    如何避免ANR错误?

    将耗时的操作放入子线程中。(耗时的操作包括:长时间的休眠,计数,联网,复杂的运算。)

    只有主线程才能操作Widget控件。

    如果在子线程中操作Widget控件,系统抛出CalledFromWrongThreadException异常。

    系统为什么要这么做?

    避免出现同步问题。

    Handler机制。

    Goolge为什么设计这套机制?

    主要是为了解决非UI线程中不能更新Widget控件的问题

    Handler机制剖析

    子线程发送消息给底层的消息队列。

    handler.sendMessage(msg)

    主线程查询消息队列,处理消息对象。

    handlerMessage(msg)

    MessageQueue 消息队列

    负责存储消息对象

    Looper

    给UI线程安排代码,一个UI线程只能有一个Looper对象,否则多个Looper对象都在UI线程上安排代码,解决冲突就是个大问题。  Looper对象会线性安排在UI线程上执行的代码,它通过一个队列管理各个Handler对象提交的代码。

    Message消息对象

    //从消息池中获取消息对象 Message msg = handler.obtainMessage(); //在消息对象上绑定int类型数据 msg.arg1 = count; //在消息对象上绑定其它类型数据 msg.setData(Bundle); //Bundler为数据集(类似于HashMap容器)

    向消息队列发送消息,1000毫秒后执行Runnable对象中的代码。

    myHandler.postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Log.e("Test", "thread name = "+Thread.currentThread().getName()); } }, 1000);

    异步任务(AsyncTask)

    概念

    封装多线程和Handler机制。给用户提供重写接口的方式,不需要用户手动创建子线程和Handler对象。

    异步任务的优点

    Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI主线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但是也有缺点,代码臃肿,在多个任务同时执行时,不易对线程进行精确的控制。为了简化操作,Android1.5提供了一个工具类AsyncTask,它是创建异步任务变的更加简单,不再需要编写任务线程和Handler实例就可完成任务。

    异步任务的局限性

    多个异步任务不能同时执行,在某个时间内,只能执行一个异步任务。

    执行异步任务的步骤: execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。 取消异步任务 /** *cancel(true) 取消当前的异步任务,传入的true,表示当中断异步任务时继续已经运行的线程的操作, *但是为了线程的安全一般为让它继续设为true **/ mTask.cancel(true); /** * 但是重新运行后会发现还是不能起到效果, * 注意:这是因为cancel方法只是发出一个请求取消异步任务的信号, * 将对应当前的异步任务标记为CANCEL状态,而并不是真正取消线程的执行, * 而此时异步任务中的线程仍然在执行并没有结束 * 所以效果依然是这样的,并且在java中我们是无法直接暴力将一个线程给停止掉 * 既然我们知道无法去取消一个已经正在运行的线程,但是我们如何去解决这个BUG呢? * 在异步任务中还给我们提供一个isCanceled的回调方法,也就是当我已经给当前的异步任务 * 调用了cancel(true)方法,发出一个请求取消异步任务的信号,那么此时的isCanceled的回调方法 * 会直接返回一个true,那么我们就可以通过判断当前异步任务isCanceled是否为true,来终止 * 线程中的操作而不是去终止线程,从而达到了界面显示好像线程中的操作被终止了,而实际上 * 该线程依然在运行 * */

    注意 异步任务对象只能执行一次。 异步任务对象必须在UI主线程中创建。execute(Params... params)方法必须在UI线程中调用。 不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。 不能在doInBackground(Params... params)中更改UI组件的信息。 基本使用 一,基本知识: (1)原型: android.os.AsyncTask<Params,Progress,Result> : 三个参数 Params --------启动任务执行的输入参数,比如HTTP请求的URL。 Progress -----后台任务执行的百分比,。 Result --------后台执行任务最终返回的结果,比如Drawable。 (2)基本步骤: 4个步骤: onPreExecute():  执行后台操作前回调的函数,常用来设置任务,例如:在用户界面中显示一个进度条。 doInBackground(Void... params) :后台执行耗时的操作,常用于接受参数返回结果,结果返回到onPostExecute()中 不能直接操作UI,在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。 onProgressUpdate(Progress...) : 在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。 onPostExecute (String result):执行后台操作完毕后自动回调此函数,后台操作结束后的结果会返回到这里,来使用 (3)基本方法: boolean   cancel(boolean mayInterruptIfRunning)  :尝试取消,如任务下载时,突然想停止,可设置XX.cancel(true); execute(Params... params)       :根据参数来开始执行 get():如果有必要,就等待计算完成,然后取它的结果 get(long timeout, TimeUnit unit)  :如果有必要,等待规定时间的计算,然后取它的结果 boolean isCancelled()    :判断操作是否已经取消了  AsyncTask.Status  getStatus()  :获取当前任务的状态, (4)4个原则: 1.异步任务的实例必须在UI线程中创建。 2.execute(Params... params)方法必须在UI线程中调用。 3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。 4.一个任务实例只能执行一次,如果执行第二次将会抛出异常。 (5)用法:一般都是一个类去继承AsyncTask,重写里面的方法,一般重写的方法有:doInBackground和onPostExecute 参考关联链接: http://blog.csdn.net/lingjianglin/article/details/52462060?locationNum=6&fps=1 http://blog.csdn.net/yubo_725/article/details/51180617?locationNum=10&fps=1

    转载请注明原文地址: https://ju.6miu.com/read-36819.html

    最新回复(0)