美文网首页
Android后台任务(HandlerThread、AsyncT

Android后台任务(HandlerThread、AsyncT

作者: 卜卜Bruce | 来源:发表于2018-04-08 22:19 被阅读0次

    线程只是最基本的应用,在复杂的场景下使用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<URL, Integer, Long> {
         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<Runnable> sPoolWorkQueue =
                new LinkedBlockingQueue<Runnable>(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方法。

    相关文章

      网友评论

          本文标题:Android后台任务(HandlerThread、AsyncT

          本文链接:https://www.haomeiwen.com/subject/wyyjhftx.html