博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android后台任务(HandlerThread、AsyncTask、IntentService)
阅读量:6231 次
发布时间:2019-06-22

本文共 4899 字,大约阅读时间需要 16 分钟。

线程只是最基本的应用,在复杂的场景下使用Thread代码可读性会变的很多差而且也容易出错。 android为了简化开发者的工作量,提供了一些更容易使用的封装。

HandlerThread

为了让Handler在非主线程工作,可以使用HandlerThread。 如题使用如下:

Handler handler;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        HandlerThread handlerThread = new HandlerThread("backThread",Process.THREAD_PRIORITY_BACKGROUND);        handlerThread.start();        handler = new Handler(handlerThread.getLooper());    }复制代码

使用HandlerThread的Looper之后,Handler就是在HandlerThread所在线程中处理消息了。 其实HandlerThread就是新建了线程,然后调用了Looper.prepare();Looper.loop();

AsyncTask

AsyncTask 现在使用的人已经不多了,它也是一个使用很简单的后台任务类,开发者不需要关注Thread和Handler就能在后台线程完成轻量级和时间较短的任务,并且最后在UI线程更新。

/*第一个为入参类型 *第二个是进度类型 *第三个是结果类型private class DownloadFilesTask extends AsyncTask
{ protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }复制代码

下面可以看方法在哪个线程调用 :

@WorkerThread    protected abstract Result doInBackground(Params... params);    @MainThread    protected void onPreExecute() {    }    @MainThread    protected void onPostExecute(Result result) {    }    @MainThread    protected void onProgressUpdate(Progress... values) {    }复制代码

其实AsyncTask有一个包含一个静态的线程池,最小同时运行两个线程,最多4个线程。

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();    // We want at least 2 threads and at most 4 threads in the core pool,    // preferring to have 1 less than the CPU count to avoid saturating    // the CPU with background work    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;    private static final int KEEP_ALIVE_SECONDS = 30;    private static final ThreadFactory sThreadFactory = new ThreadFactory() {        private final AtomicInteger mCount = new AtomicInteger(1);        public Thread newThread(Runnable r) {            return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());        }    };    private static final BlockingQueue
sPoolWorkQueue = new LinkedBlockingQueue
(128); /** * An {
@link Executor} that can be used to execute tasks in parallel. */ public static final Executor THREAD_POOL_EXECUTOR; static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); THREAD_POOL_EXECUTOR = threadPoolExecutor; }复制代码

其中还有一个handler用于更新UI线程。

private static Handler getMainHandler() {        synchronized (AsyncTask.class) {            if (sHandler == null) {                sHandler = new InternalHandler(Looper.getMainLooper());            }            return sHandler;        }    }    private Handler getHandler() {        return mHandler;    }复制代码

由于都是静态的,所以其实所有的AsyncTask都是公用这个线程池和Handler。 AsyncTask使用起来也很简单,但是有一些限制,只能在UI线程实例化和调用。

new DownloadFilesTask().execute(url1,url2,url3);复制代码

IntentService

IntentService是为了处理异步任务而对Service的封装。 其实原理也很简单。

private final class ServiceHandler extends Handler {        public ServiceHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(Message msg) {            onHandleIntent((Intent)msg.obj);            stopSelf(msg.arg1);        }    }    @Override    public void onCreate() {        // TODO: It would be nice to have an option to hold a partial wakelock        // during processing, and to have a static startService(Context, Intent)        // method that would launch the service & hand off a wakelock.        super.onCreate();        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");        thread.start();        mServiceLooper = thread.getLooper();        mServiceHandler = new ServiceHandler(mServiceLooper);    }    @Override    public void onStart(@Nullable Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }复制代码

就是在Service的OnCreate里创建了一个HandlerThread,然后把需要处理的Intent发送到这个Handler在后台线程中处理并且完毕后调用stopSelf关闭服务。

使用上和Service一样,就是需要重写onHandleIntent方法。

转载于:https://juejin.im/post/5c8753bc5188257e453c6400

你可能感兴趣的文章
word文档的动态添加数据
查看>>
模仿ReentrantLock类自定义锁
查看>>
Redis进阶实践之九 独立封装的RedisClient客户端工具类
查看>>
如何在Python中从零开始实现随机森林
查看>>
动态规划-最优二叉搜索树-公式推导
查看>>
jquery获取前一个月日期
查看>>
R12.2常用手册
查看>>
【全网最全的博客美化系列教程】01.添加Github项目链接
查看>>
[微信小程序] 通过快速启动demo分析小程序入门关键点
查看>>
C# 封装miniblink 使用HTML/CSS/JS来构建.Net 应用程序界面和简易浏览器
查看>>
SQL Server管理员必备技能之性能优化
查看>>
组合拳出击-Self型XSS变废为宝
查看>>
服务网与各地落地平台的调用关系
查看>>
使用VAE、CNN encoder+孤立森林检测ssl加密异常流的初探——真是一个忧伤的故事!!!...
查看>>
13个在企业中持上升势头的开源编程工具
查看>>
sql server 2005附加数据库错误:尝试打开或创建物理文件时,CREATE FILE 遇到操作系统错误...
查看>>
彻底搞定C指针-函数名与函数指针
查看>>
win7快速启动栏
查看>>
一个网络项目招标书,大神们会几个?
查看>>
基于x86和JVM浅谈32bit与64bit的区别
查看>>