美文网首页
Android 异步处理

Android 异步处理

作者: tuacy | 来源:发表于2018-06-17 12:50 被阅读67次

           咱们都知道在Android主线程中处理耗时任务会产生ANR,所有很多耗时的任务都需要异步处理。Android里面的有四种常见的异步处理类见:Thread、HandlerThread、AsyncTask、IntentService。

    一、Thread

           线程是执行任务的最基本的单元,当然了在Android中线程分为两大部分:主线程、子线程。Thread线程主要有以下几种状态:

    • New:实例被创建。
    • Runnable:就绪状态。
    • Running:线程被cpu执行调用run()函数之后 就处于运行状态。
    • Blocked:调用join()函数、sleep()函数、wait()函数使线程处于阻塞状态。
    • Dead:线程的run()方法运行完毕或被中断或被异常退出,线程将会到达Dead状态。

           当需要新起一个线程来执行某个子任务时,就创建了一个线程。但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内存资源、Java栈、本地方法栈都是线程私有的,所以需要为线程分配一定的内存空间),只有线程运行需要的所有条件满足了,才进入就绪状态。当线程进入就绪状态后,不代表立刻就能获取CPU执行时间,也许此时CPU正在执行其他的事情,因此它要等待。当得到CPU执行时间之后,线程便真正进入运行状态。

    1.1、Thread实现方式

           实现线程有两种方式:继承Thread类、以及实现Runnable接口

    1.1.1、继承Thread类

        private class YourThread extends Thread {
    
            YourThread(String name) {
                super(name);
            }
    
            @Override
            public void run() {
                //执行耗时操作,做你想做的
            }
        }
    
        YourThread yourThread = new YourThread("我的线程");
        yourThread.start();
    

    1.1.2、实现Runnable接口

        private class YourRunnable implements Runnable {
            @Override
            public void run() {
                //执行耗时操作,做你想做的
            }
        }
    
        Thread yourThread = new Thread(new YourRunnable(), "我的线程");
        yourThread.start();
    

           Thread两种实现方式,推荐使用实现Runnable接口的方式。因为 当继承了Thread类,则不能继承其他类,而实现Runnable接口可以,而且实现Runnable接口的线程类的多个线程,可以访问同一变量,而Thread则不能。

    1.2、Thread 主要函数介绍

        /**
         * 线程运行时需要执行的代码
         */
        public void run()
    
        /**
         * 启动线程
         */
        public synchronized void start()
    
        /**
         * 线程休眠,交出CPU,让CPU去执行其他的任务,然后线程进入阻塞状态,sleep方法不会释放同步锁
         *
         * @param millis 休眠时间,单位毫秒
         */
        public static void sleep(long millis) throws InterruptedException
        /**
         * @param millis 休眠时间,单位毫秒
         * @param nanos  额外的休眠时间,单位纳秒
         */
        public static void sleep(long millis, int nanos) throws InterruptedException
    
        /**
         * 线程让步,使当前线程交出CPU,当前线程重置为就绪状,然后又通过和其他线程公平竞争来看谁先执行。yield方法不会释放锁
         */
        public static native void yield()
    
        /**
         * 等待线程终止,再继续执行。直白的说 就是发起该子线程的线程 只有等待该子线程运行结束才能继续往下运行
         */
        public final void join() throws InterruptedException
        /**
         * @param millis 等待时间,单位毫秒
         */
        public final void join(long millis) throws InterruptedException
        /**
         * @param millis 等待时间,单位毫秒
         * @param nanos  额外等待时间,单位纳秒
         */
        public final void join(long millis, int nanos) throws InterruptedException
    
        /**
         * 中断线程,我们通过interrupt方法和isInterrupted()方法来停止正在运行的线程,注意只能中断已经处于阻塞的线程
         */
        public void interrupt()
    
        /**
         * 获取当前线程id
         */
        public long getId()
    
        /**
         * 设置获取当前线程的名字
         */
        public final void setName(String name)
        public final String getName()
    
        /**
         * 设置获取当前线程优先级
         */
        public final void setPriority(int newPriority)
        public final int getPriority()
    
        /**
         * 设置和判断是否是守护线程 setDaemon()函数一点要在start()函数之前调用
         */
        public final void setDaemon(boolean on)
        public final boolean isDaemon()
    
        /**
         * 获取当前线程
         */
        public static native Thread currentThread()
    

    1.2.1、sleep(),wait(),yield(),join()函数的区别。

    • sleep():在指定时间内让当前正在执行的线程暂停执行,可以执行其他的任务,但不会释放“锁标志”。
    • wait():java.lang.Object类里面提供的方法,暂停执行,wait方法释放了“锁标志”,使得其他线程可以使用同步控制块或者方法。wait之后需要调用notify和notifyAll来通知往下执行。

    wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用。

    • yield():当前线程让步,当前线程又重新进入就绪状态。又和其他线程公平竞争看谁先执行。(注意哦:并不是完完全全的让给其他线程了,而是又重新竞争哦,有可能还是自己执行也有可能是其他的线程执行)。
    • join():等待线程结束。

    1.2.2、用户线程和守护线程

           Java里面将线程分为User Thread(用户线程)和Daemon Thread(守护线程)两种。Daemon Thread是运行在后台的线程。我们Android里面的MainThread就是User Thread而不是Daemon Thread。Daemon Thread一般用来给User Thread提供服务。

    调用setDaemon()函数去设置是否是守护线程的时候,该函数一点要在start()函数之前调用。否则无效。

    1.3、如何优雅的终止Thread

           JDK里面Thread提供了一个stop()方法,但是stop()方法是一个被废弃的方法。为什么stop()方法被废弃而不被使用呢?因为stop()方法太过于暴力,会强行把执行一半的线程终止。这样会就不会保证线程的资源正确释放,通常是没有给与线程完成资源释放工作的机会,因此会导致程序工作在不确定的状态下。既然stop()方法不让用了,那咱们还有哪些方法来终止Thread呢。

    1.3.1、监视某个退出标志位

           简单地设置一个标志位,需要配合while()循环使用,并通过设置这个标志来控制循环是否退出。

        public class YourThread extends Thread {
    
            public volatile boolean mExit = false;
    
            @Override
            public void run() {
                super.run();
                while (!mExit) {
                    System.out.println("I'm running");
                }
            }
        }
    

    1.3.2、使用interrupt方法终止线程

           调用interrupt()方法之后interrupted()结果为true,最后采用抛异常的方式来终止线程,代码如下:

        public class YourThread extends Thread {
    
            @Override
            public void run() {
                try {
                    while (true) {
                        if (interrupted()) {
                            throw new InterruptedException();
                        }
                        System.out.println("I'm running");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }
    

    二、HandlerThread

           HandlerThread是实现了Lopper的线程(归根到底他还是一个线程)。为什么需要HandlerThread这东西呢,因为Android中为了同时完成多个任务,经常会在应用程序当中创建多个线程。这个时候为了让多个线程之间能够方便的通信,这个时候我们通常会使用Handler实现线程间的通信。但是Handler对应的线程必须包含Looper(Android主线程默认已经包含Looper了)。默认线程是没有Looper的。不过我们可以自己去创建Looper,为线程创建Looper的方法如下:在线程run()方法当中先调用Looper.prepare()初始化Looper,然后再run()方法最后调用Looper.loop()启动循环。那,现在为了方便大家不用我们每次都去写这些Looper的创建。Android API就给我们提供了HandlerThread。

    记住,想通过Handler把消息发送到那个线程里面去,对应的线程必须包含Looper。

    2.1、HandlerThread使用

           HandlerThread使用步骤:

    • 创建HandlerThread线程。
    • 启动HandlerThread线程。
    • 创建Handler对象,Lopper必须是HandlerThread里面的Looper。(Hander用于发送消息)
    • 用完之后记得退出循环,要不然HandlerThread线程一直占内存。
    ublic class HandlerThreadActivity extends MobileBaseActivity {
    
        private HandlerThread mHandlerThread;
        private Handler       mHandler;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //创建一个线程,线程名字:handler-thread
            mHandlerThread = new HandlerThread("handler-thread");
            //开启一个线程
            mHandlerThread.start();
            mHandler = new Handler(mHandlerThread.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    //这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
                    Log.d("handler ", "消息: " + msg.what + "  线程: " + Thread.currentThread().getName());
                }
            };
            //在主线程给handler发送消息
            mHandler.sendEmptyMessage(1);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //释放资源
            mHandlerThread.quit();
        }
    }
    

    千万要记得HandlerThread用完之后要调用quit()方法退出循环。

    2.2、HandlerThread源码实现过程

           上面对HandlerThread的使用做了一个很简单的介绍,接下来咱们就来具体的看下HandlerThread的源码。对于HandlerThread得明确他是一个带Looper的线程。

           HandlerThread源文件也非常的简单,如下

    public class HandlerThread extends Thread {
    
        ...
    
        /**
         * 线程开始loop之前的回调
         */
        protected void onLooperPrepared() {
        }
    
        @Override
        public void run() {
            mTid = Process.myTid();
            Looper.prepare();
            synchronized (this) {
                mLooper = Looper.myLooper();
                notifyAll();
            }
            Process.setThreadPriority(mPriority);
            onLooperPrepared();
            Looper.loop();
            mTid = -1;
        }
    
        /**
         * 获取Looper对象
         */
        public Looper getLooper() {
            if (!isAlive()) {
                return null;
            }
    
            // If the thread has been started, wait until the looper has been created.
            synchronized (this) {
                while (isAlive() && mLooper == null) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                    }
                }
            }
            return mLooper;
        }
    
        /**
         * 退出looper循环()
         */
        public boolean quit() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quit();
                return true;
            }
            return false;
        }
    
        /**
         * 和quit()方法一样,只不过这个更加的安全
         */
        public boolean quitSafely() {
            Looper looper = getLooper();
            if (looper != null) {
                looper.quitSafely();
                return true;
            }
            return false;
        }
    
        ...
    
    }
    

           这里我们主要关注run()方法里面的内容,其他的方法都很简单,大家肯定一看就懂。run()方法里面开始的时候调用了Looper.prepare();,run()方法快结束的时候调用了Looper.loop();这样就让HandlerThread循环起来了。run()方法里面大家有发现notifyAll();的调用把。这干啥的呀。来我们先看getLooper()方法了,是不是在getLopper()方法里面mLooper = null的时候调用了wait()。当mLooper=null的时候getLopper()就一直等在这里了,等mLooper不为null的时候才返回mLooper。notifyAll()就是run()方法里面获取到了mLooper之后通知wait()不用等了,可以去获取了。

    三、AsyncTask

           AsyncTask是Android提供的另一个异步处理的工具类,它对Thread和Handler进行了封装,方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行UI更新等操作。使用AsyncTask的时候,我们无需关注Thread和Handler,AsyncTask内部会对其进行管理,这样我们就只需要关注于我们的业务逻辑即可。

           AsyncTask有四个重要的回调方法,分别是:onPreExecute、doInBackground, onProgressUpdate 和 onPostExecute。这四个方法会在AsyncTask的不同时期进行自动调用,我们只需要实现这几个方法的内部逻辑即可。这四个方法的一些参数和返回值都是基于泛型的,而且泛型的类型还不一样,所以在AsyncTask的使用中会遇到三种泛型参数:Params, Progress 和 Result。

    四个重要方法介绍

    • onPreExecute():运行在UI线程,后台任务即将开始。
    • doInBackground():运行在单独的工作线程中,处理后台任务逻辑。
    • onProgressUpdate():运行在UI线程,一般用于回传任务处理的进度。
    • onPostExecute():运行在UI线程,后台任务执行完毕。

    三种泛型介绍

    • Params:开始异步任务执行时传入的参数类型。
    • Progress:异步任务执行过程中,返回下载进度值的类型。
    • Result:异步任务执行完成后,返回的结果类型。

    3.1、AsyncTask使用

           AsyncTask使用也非常简单,主要的关注点都在我们的业务逻辑上。比如我们来实现一个文件下载的任务。伪代码如下:

    public class AsyncTaskActivity extends MobileBaseActivity {
    
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            String[] urls = {"http://blog.csdn.net/iispring/article/details/47115879"};
    
            DownloadTask downloadTask = new DownloadTask();
            //开始执行任务
            downloadTask.execute(urls);
        }
    
        /**
         * Params - > String:文件url
         * Progress - > Float 文件下载进度
         * Result - > Long 下载的文件大小
         */
        private class DownloadTask extends AsyncTask<String, Float, Long> {
    
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                //TODO:UI线程执行,开始执行任务的回调
            }
    
            @Override
            protected Long doInBackground(String... strings) {
                //TODO:1. 从参数里面获取到文件的下载地址。2. while循环读取网络文件信息,并且实时调用publishProgress告诉下载进度
                downloadTask(strings[0]);
                return null;
            }
    
            @Override
            protected void onProgressUpdate(Float... values) {
                super.onProgressUpdate(values);
                //TODO:下载进度回调上来
            }
    
            @Override
            protected void onPostExecute(Long aLong) {
                super.onPostExecute(aLong);
                //TODO:任务执行完成
            }
    
            private void downloadTask(String path) {
                //模拟耗时操作
                int count = 0;
                try {
                    while (count < 100) {
                        count++;
                        Thread.sleep(3 * 1000);
                        publishProgress((float) count);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    3.2、AsyncTask源码实现过程

           AsyncTask源代码的分析。

           先从构造函数开始,

    构造函数

        public AsyncTask(@Nullable Looper callbackLooper) {
            mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
    
            mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return result;
                }
            };
    
            mFuture = new FutureTask<Result>(mWorker) {
                @Override
                protected void done() {
                    try {
                        postResultIfNotInvoked(get());
                    } catch (InterruptedException e) {
                        android.util.Log.w(LOG_TAG, e);
                    } catch (ExecutionException e) {
                        throw new RuntimeException("An error occurred while executing doInBackground()",
                                e.getCause());
                    } catch (CancellationException e) {
                        postResultIfNotInvoked(null);
                    }
                }
            };
        }
    

           就是初始化了三个变量,mHandler、mWorker、mFuture。mHandler是用来post消息的,把onProgressUpdate()和onPostExecute()post到主线程里面去执行。

           接着,如果AsyncTask想执行任务,会调用execute()函数,我们直接看下execute()函数。

    execute()

        @MainThread
        public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
    

           execute()函数直接调用了executeOnExecutor()函数。注意第一个参数是sDefaultExecutor。他是一个static修饰变量,是所有AsyncTask共有的。

    sDefaultExecutor

        private static class SerialExecutor implements Executor {
            final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
            Runnable mActive;
    
            public synchronized void execute(final Runnable r) {
                mTasks.offer(new Runnable() {
                    public void run() {
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });
                if (mActive == null) {
                    scheduleNext();
                }
            }
    
            protected synchronized void scheduleNext() {
                if ((mActive = mTasks.poll()) != null) {
                    THREAD_POOL_EXECUTOR.execute(mActive);
                }
            }
        }
    
    

           分析代码我们发现sDefaultExecutor会把所有的任务依次加入到线程池中,而且保证了先进来的任务加入线程池,执行完一个任务就加入一个线程池。其中线程池THREAD_POOL_EXECUTOR也是一个static变量。

    executeOnExecutor()

        @MainThread
        public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
                Params... params) {
            if (mStatus != Status.PENDING) {
                switch (mStatus) {
                    case RUNNING:
                        throw new IllegalStateException("Cannot execute task:"
                                + " the task is already running.");
                    case FINISHED:
                        throw new IllegalStateException("Cannot execute task:"
                                + " the task has already been executed "
                                + "(a task can be executed only once)");
                }
            }
    
            mStatus = Status.RUNNING;
    
            onPreExecute();
    
            mWorker.mParams = params;
            exec.execute(mFuture);
    
            return this;
        }
    
    

           先判断了状态,看的出来一个AsyncTask只能excute一次。在接着调用onPreExecute(); 回调告诉任务准备开始了。最后exec.execute(mFuture);把mFuture加入到sDefaultExecutor里面去。mFuture在构造函数里面已经声明了。从构造函数得知会执行mWorker变量的call()函数,call()函数执行完之后会执行mFuture对象的done()函数。

    先执行mWorker的call()函数

            mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return result;
                }
            };
    

    mWorker的call()函数执行完之后执行mFuture的done()函数

            mFuture = new FutureTask<Result>(mWorker) {
                @Override
                protected void done() {
                    try {
                        postResultIfNotInvoked(get());
                    } catch (InterruptedException e) {
                        android.util.Log.w(LOG_TAG, e);
                    } catch (ExecutionException e) {
                        throw new RuntimeException("An error occurred while executing doInBackground()",
                                e.getCause());
                    } catch (CancellationException e) {
                        postResultIfNotInvoked(null);
                    }
                }
            };
    

           mWorker的call()函数里面调用了doInBackground()吧,并且是在后台线程中执行的。call()函数的最后调用了postResult(result);把结果回调给主线程。

           我们看下postResult()是怎么回调到主线程的。

    postResult()函数

        private Result postResult(Result result) {
            @SuppressWarnings("unchecked")
            Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
        }
    

    很熟悉把,getHandler()对应的是哪个线程,就去哪个线程执行了。

        private static class InternalHandler extends Handler {
            public InternalHandler(Looper looper) {
                super(looper);
            }
    
            @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
            @Override
            public void handleMessage(Message msg) {
                AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
                switch (msg.what) {
                    case MESSAGE_POST_RESULT:
                        // There is only one result
                        result.mTask.finish(result.mData[0]);
                        break;
                    case MESSAGE_POST_PROGRESS:
                        result.mTask.onProgressUpdate(result.mData);
                        break;
                }
            }
        }
    

           其中两种消息类型MESSAGE_POST_RESULT、MESSAGE_POST_PROGRESS一个用来回调执行结果的,一个用来回调执行进度的。一个对应onPostExecute()的回调,一个对应onProgressUpdate()的回调。当然了如果你想触发onProgressUpdate()执行进度的回调,你的自己在doInBackground()里面主动的去调用publishProgress()函数。

           AsyncTask源码的分析过程关键是抓住onPreExecute、doInBackground, onProgressUpdate 和 onPostExecute函数的调用位置和所处的线程。AsyncTask的简单分析就到这里有疑问也可以留言。

    四、IntentService

           IntentService 是继承自 Service 并处理异步任务的一个类。IntentServicer最大的特点是用完即走。处理玩异步任务IntentService会自动结束。

    4.1、IntentService的使用

           IntentService有一个非常重要的方法onHandleIntent(),onHandleIntent()当某个请求需要处理时,这个方法会在工作者线程被调用,一次仅仅会有一个请求被处理。所以我们在onHandleIntent()函数里面处理我们的异步逻辑。

    写一个非常的下载例子

    public class IntentServiceActivity extends MobileBaseActivity {
    
        public final static String ACTION_TYPE_THREAD = "action.type.thread";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            // 启动异步任务
            DownloadIntentService.startDownload(IntentServiceActivity.this, "image path");
        }
    
        static class DownloadIntentService extends IntentService {
    
            public static final String EXTRA_DOWNLOAD_IMAGE = "com.tuacy.convenientinputedit.DOWNLOAD_IMAGE";
    
            public DownloadIntentService() {
                super("DownloadIntentService");
            }
    
            public static void startDownload(Context context, String path) {
                Intent intent = new Intent(context, DownloadIntentService.class);
                intent.putExtra(EXTRA_DOWNLOAD_IMAGE, path);
                context.startService(intent);
            }
    
            @Override
            protected void onHandleIntent(Intent intent) {
                if (intent != null) {
                    String path = intent.getStringExtra(EXTRA_DOWNLOAD_IMAGE);
                    downloadTask(path);
                }
            }
    
            private void downloadTask(String path) {
                //模拟耗时操作
                try {
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //利用广播通知主界面更新
                Intent intent = new Intent(IntentServiceActivity.ACTION_TYPE_THREAD);
                intent.putExtra(EXTRA_DOWNLOAD_IMAGE, path);
                sendBroadcast(intent);
            }
    
            @Override
            public void onCreate() {
                super.onCreate();
            }
    
            @Override
            public void onDestroy() {
                super.onDestroy();
            }
        }
    
    }
    

    IntentService的启动方式采用startService()。

    4.2、IntentService源码分析

           IntentService的源码也非常的简单。我们做一个简单的分析。

    public class IntentService extends Service {
    
        private volatile ServiceHandler mServiceHandler;
    
        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() {
    
            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);
        }
        
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            onStart(intent, startId);
            return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
        }
    
        ...
    }
    

           通过startService()方式启动Service之后会先回调onCreate()方法,然后回调onStart()或者onStartCommand()方法(android2.0以下调用onStart(),android2.0之上调用onStartCommand()方法)。onCreate()方法里面启动了一个HandlerThread线程。并且mServiceHandler绑定到HandlerThread线程上去了。后面通过mServiceHandler发送的消息都会在这个HandlerThread线程里面执行。onStart()的回调函数马上就发送了一个消息出去,消息到ServiceHandler类的handleMessage()里面处理。调用onHandleIntent()函数,之后调用stopSelf()整个IntentService也就自动停止了。


           以上就是对Android里面的异步处理做了一个简单的总结。

    相关文章

      网友评论

          本文标题:Android 异步处理

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