zoukankan      html  css  js  c++  java
  • android--线程

    进程优先级

    Foreground Process:前台进程,用户可见,被遮挡,虽然可见,但是不属于前台进程;

    Background Process:后台进程,用户不可见,进程包含service,重要性高,也存在空进程,不做任何事情。

    先立个大纲,明天写吧(2017年1月11日20:19:49)

    线程调度

    1. 线程在程序中是独立的,并发的执行流,与进程相比,进程中的线程隔离程度小,共享内存,文件句柄,和进程应有的状态。
    2. 进程执行过程中拥有独立内存单元,多线程共享内存,提高程序运行效率。
    3. 线程共享进程代码段,进程共有数据,可很容易实现线程间相互通信。
    4. 进程间不能共享内存,线程共享相对容易的多。
    5. 创建线程实现多任务并发比多线程来说效率高。

    thread runnable

    创建线程和启动线程:

    继承自Thread,重写run方法;

    实现Runnable接口,并重写Runnable的run方法;

    1 public class MyThread extends Thread {
    2 
    3     @Override
    4     public void run() {
    5         super.run();
    6         Log.i("MyThreadName = ",this.getName());
    7     }
    8 }
    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            Log.i("MyRunnable_ThreadName=",Thread.currentThread().getName());
        }
    }

    两种实现方式的区别:

    采用Runnable实现,

    1. 线程类只是实现Runnable接口还可以继承自其他类;
    2. 可以实现共享同一target对象,使用相同线程处理同一资源的情况。

    采用Thread实现:

    不能继承其他父类;

    无需使用Thread,currentThread()来获取当前线程,使用this就行。

    线程生命周期:

    new 新建状态,java虚拟机分配内存并初始化成员变量的值。

    start 就绪状态,虚拟机创建栈和程序计数器,线程没有开始运行,只是可以运行。

    运行状态:就绪状态线程获得CPU,执行run方法的线程执行体。

    阻塞状态:

    • 线程调用sleep方法主动放弃所占用的处理器资源;
    • 线程调用阻塞IO方法,在该方法返回之前,线程阻塞;
    • 线程获取同步监视器,同步监视器被其他线程持有;
    • 线程等待通知(notify);
    • 线程调用suspend将线程挂起,容易死锁,不建议使用。

    重新进入就绪状态:

    • 调用sleep的线程到了指定时间;
    • 线程阻塞io已经返回;
    • 线程成功获取同步监视器;
    • 线程正在等待通知,其他线程发出通知;
    • 处于关闭的线程调用resume恢复。

     线程死亡:

    • run方法执行完成,线程正常结束;
    • 线程抛出Exception或者Error;
    • 直接调用线程stop方法结束该线程(容易死锁,不建议使用)。

     控制线程:

    join()方法:调用线程阻塞,知道被join方法加入的join线程完成为止;

    • join():等待被join线程执行完成;
    • join(long millis):等待被join时间最长为millis毫秒,如果超出millis毫秒时间则不继续等待;
    • join(long millis, int nanos):等待被join的线程时间为millis毫秒+nanos微秒;

     AsyncTask

    轻量级异步任务类,内部封装了Thread和Handler,但是不适合特别耗时的后台任务,特别耗时间的建议使用线程池。

    三个泛型参数

      1. Params
      在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。
      2. Progress
      后台任何执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
      3. Result
      当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

    几个核心方法:

      1. onPreExecute()(UI线程)
      这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框。
      2. doInBackground(Params...)(异步子线程)
      这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回,如果AsyncTask的第三个泛型参数指定的是Void,就可以不返回任务执行结果。注意,在这个方法中是不可以进行UI操作的,如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
      3. onProgressUpdate(Progress...)(UI线程)
    当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
      4. onPostExecute(Result)(UI线程)
      当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如关闭掉进度条对话框。

     注意点:

    1. AsyncTask必须主线程调用;
    2. AsyncTask必须主线程创建对象;
    3. execute必须主线程调用;
    4. android 1.6之前 串行执行任务,1.6改成线程池并行执行,android3.0后采用一个线程串行执行,但是可以调用executeOnExcutor方法来并行执行任务。

     AnsyTask源码分析:

     首先ansyTask是一个抽象类,需要子类去实现:

    1 public abstract class AsyncTask<Params, Progress, Result>{
    2 
    3 }

    因为要调用AnsyTask需要初始化对象,所以我们先看下它的构造方法:

     1 /**
     2      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     3      */
     4     public AsyncTask() {
     5         mWorker = new WorkerRunnable<Params, Result>() {
     6             public Result call() throws Exception {
     7                 mTaskInvoked.set(true);
     8 
     9                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    10                 //noinspection unchecked
    11                 Result result = doInBackground(mParams);
    12                 Binder.flushPendingCommands();
    13                 return postResult(result);
    14             }
    15         };
    16 
    17         mFuture = new FutureTask<Result>(mWorker) {
    18             @Override
    19             protected void done() {
    20                 try {
    21                     postResultIfNotInvoked(get());
    22                 } catch (InterruptedException e) {
    23                     android.util.Log.w(LOG_TAG, e);
    24                 } catch (ExecutionException e) {
    25                     throw new RuntimeException("An error occurred while executing doInBackground()",
    26                             e.getCause());
    27                 } catch (CancellationException e) {
    28                     postResultIfNotInvoked(null);
    29                 }
    30             }
    31         };
    32     }

    必须在UI线程进行初始化操作,初始化mWorker,mFuture两个对象,初始化mWorker首先 mTaskInvoked.set(true);表示当前任务已经被调用过了,mWorker调用AsyncTask的doinBackground执行耗时操作,返回值传递给postResult方法。

    看下postResult方法:

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

    看下hander:

    1 private static Handler getHandler() {
    2         synchronized (AsyncTask.class) {
    3             if (sHandler == null) {
    4                 sHandler = new InternalHandler();
    5             }
    6             return sHandler;
    7         }
    8     }
     1 private static class InternalHandler extends Handler {
     2         public InternalHandler() {
     3             super(Looper.getMainLooper());
     4         }
     5 
     6         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
     7         @Override
     8         public void handleMessage(Message msg) {
     9             AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
    10             switch (msg.what) {
    11                 case MESSAGE_POST_RESULT:
    12                     // There is only one result
    13                     result.mTask.finish(result.mData[0]);
    14                     break;
    15                 case MESSAGE_POST_PROGRESS:
    16                     result.mTask.onProgressUpdate(result.mData);
    17                     break;
    18             }
    19         }
    20     }

    很明显调用第13行进而调用:

    1  private void finish(Result result) {
    2         if (isCancelled()) {
    3             onCancelled(result);
    4         } else {
    5             onPostExecute(result);
    6         }
    7         mStatus = Status.FINISHED;
    8     }

    如果取消调用onCancelled(result)否则调用onPostExcute(result)进行UI线程的操作。

    然后我们代码中还会调用execute()方法:

    1 @MainThread
    2     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    3         return executeOnExecutor(sDefaultExecutor, params);
    4     }
     1 @MainThread
     2     public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
     3             Params... params) {
     4         if (mStatus != Status.PENDING) {
     5             switch (mStatus) {
     6                 case RUNNING:
     7                     throw new IllegalStateException("Cannot execute task:"
     8                             + " the task is already running.");
     9                 case FINISHED:
    10                     throw new IllegalStateException("Cannot execute task:"
    11                             + " the task has already been executed "
    12                             + "(a task can be executed only once)");
    13             }
    14         }
    15 
    16         mStatus = Status.RUNNING;
    17 
    18         onPreExecute();
    19 
    20         mWorker.mParams = params;
    21         exec.execute(mFuture);
    22 
    23         return this;
    24     }

    sDefaultExecutor:

     1 public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
     2  private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
     3 private static class SerialExecutor implements Executor {
     4         final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
     5         Runnable mActive;
     6 
     7         public synchronized void execute(final Runnable r) {
     8             mTasks.offer(new Runnable() {
     9                 public void run() {
    10                     try {
    11                         r.run();
    12                     } finally {
    13                         scheduleNext();
    14                     }
    15                 }
    16             });
    17             if (mActive == null) {
    18                 scheduleNext();
    19             }
    20         }
    21 
    22         protected synchronized void scheduleNext() {
    23             if ((mActive = mTasks.poll()) != null) {
    24                 THREAD_POOL_EXECUTOR.execute(mActive);
    25             }
    26         }
    27     }

     首先给ArrayDeque<Runnable>队列尾部插入runnable对象,run里面如果出现异常调用Executor的excute方法(THREAD_POOL_EXECUTOR.execute(mActive););


    HandlerThread

     如下面代码所示:HandlerThread是继承自Thread,并且可使用Handler的Thread,通过在线程里面实现Looper.prepare()和Looper.loop()实现创建队列,和轮训队列的操作。

    HandlerThread源码:

      1 /**
      2  * Handy class for starting a new thread that has a looper. The looper can then be 
      3  * used to create handler classes. Note that start() must still be called.
      4  *启动一个携带有looper的线程,用来创建handler类。启动这个线程通过start()来实现。
      5  */
      6 public class HandlerThread extends Thread {
      7   //线程的优先级
      8     int mPriority;
      9   //当前线程id
     10     int mTid = -1;
     11   //当前线程持有的Looper对象
     12     Looper mLooper;
     13   
     14   //有参构造方法,优先级为默认优先级,
     15     public HandlerThread(String name) {
     16         super(name);
     17         mPriority = Process.THREAD_PRIORITY_DEFAULT;
     18     }
     19     
     20     /**
     21      * Constructs a HandlerThread.
     22    *有参数构造方法,可以手动传递线程优先级。
     23      * @param name
     24      * @param priority The priority to run the thread at. The value supplied must be from 
     25      * {@link android.os.Process} and not from java.lang.Thread.
     26      */
     27     public HandlerThread(String name, int priority) {
     28         super(name);
     29         mPriority = priority;
     30     }
     31     
     32     /**
     33      * Call back method that can be explicitly overridden if needed to execute some
     34      * setup before Looper loops.
     35    *回调方法可以实现在Looper.loop()之前的操作
     36      */
     37     protected void onLooperPrepared() {
     38     }
     39 
     40    /**
     41     *关键部分
     42     *
     43     */
     44 
     45     @Override
     46     public void run() {
     47      //获得当前线程的id
     48         mTid = Process.myTid();
     49      //准备循环条件
     50         Looper.prepare();
     51         synchronized (this) {
               //获取到Looper对象 52 mLooper = Looper.myLooper();
               //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait 53 notifyAll(); 54 }
            //设置线程优先级 55 Process.setThreadPriority(mPriority);
            //子类重写方法,进行循环操作之前的操作 56 onLooperPrepared();
            //进行循环操作,不断的从MessageQueue中获取Message进行分发操作 57 Looper.loop(); 58 mTid = -1; 59 } 60 61 /** 62 * This method returns the Looper associated with this thread. If this thread not been started 63 * or for any reason is isAlive() returns false, this method will return null. If this thread 64 * has been started, this method will block until the looper has been initialized. 65 * @return The looper.
          *获取Looper对象,如果这个线程没start()或者其他原因,比如线程不存活isAlive为false的时候,这个方法返回null,如果线程启动了,这个放回会阻塞知道Looper初始化。 66 */ 67 public Looper getLooper() { 68 if (!isAlive()) { 69 return null; 70 } 71 72 // If the thread has been started, wait until the looper has been created.
            //如果线程已经启动,但是Looper还未创建的话,就等待,直到Looper创建成功
    73 synchronized (this) { 74 while (isAlive() && mLooper == null) { 75 try { 76 wait(); 77 } catch (InterruptedException e) { 78 } 79 } 80 } 81 return mLooper; 82 } 83 84 /** 85 * Quits the handler thread's looper. 86 * <p> 87 * Causes the handler thread's looper to terminate without processing any 88 * more messages in the message queue. 89 * </p><p> 90 * Any attempt to post messages to the queue after the looper is asked to quit will fail. 91 * For example, the {@link Handler#sendMessage(Message)} method will return false. 92 * </p><p class="note"> 93 * Using this method may be unsafe because some messages may not be delivered 94 * before the looper terminates. Consider using {@link #quitSafely} instead to ensure 95 * that all pending work is completed in an orderly manner. 96 * </p> 97 * 98 * @return True if the looper looper has been asked to quit or false if the 99 * thread had not yet started running. 100 * 101 * @see #quitSafely
          *结束线程循环,通过调用Looper的quit方法,其实最后调用是消息队列的quit方法。 102 */ 103 public boolean quit() { 104 Looper looper = getLooper(); 105 if (looper != null) { 106 looper.quit(); 107 return true; 108 } 109 return false; 110 } 111 112 /** 113 * Quits the handler thread's looper safely. 114 * <p> 115 * Causes the handler thread's looper to terminate as soon as all remaining messages 116 * in the message queue that are already due to be delivered have been handled. 117 * Pending delayed messages with due times in the future will not be delivered. 118 * </p><p> 119 * Any attempt to post messages to the queue after the looper is asked to quit will fail. 120 * For example, the {@link Handler#sendMessage(Message)} method will return false. 121 * </p><p> 122 * If the thread has not been started or has finished (that is if 123 * {@link #getLooper} returns null), then false is returned. 124 * Otherwise the looper is asked to quit and true is returned. 125 * </p> 126 * 127 * @return True if the looper looper has been asked to quit or false if the 128 * thread had not yet started running.
          *线程安全的退出线程的循环,其实最后也是调用的消息队列的quit方法 129 */ 130 public boolean quitSafely() { 131 Looper looper = getLooper(); 132 if (looper != null) { 133 looper.quitSafely(); 134 return true; 135 } 136 return false; 137 } 138 139 /** 140 * Returns the identifier of this thread. See Process.myTid().
          *获取线程id 141 */ 142 public int getThreadId() { 143 return mTid; 144 } 145 }

    第50行调用如下代码,进行Looper的初始化操作

     1 /** Initialize the current thread as a looper.
     2       * This gives you a chance to create handlers that then reference
     3       * this looper, before actually starting the loop. Be sure to call
     4       * {@link #loop()} after calling this method, and end it by calling
     5       * {@link #quit()}.
          *进行初始化操作,通过Looper.loop()进行循环处理,通过调用quit结束操作。 6 */ 7 public static void prepare() { 8 prepare(true); 9 } 10 11 private static void prepare(boolean quitAllowed) { 12 if (sThreadLocal.get() != null) { 13 throw new RuntimeException("Only one Looper may be created per thread"); 14 } 15 sThreadLocal.set(new Looper(quitAllowed)); 16 }

    消息队列里面的quit方法:

     1   void quit(boolean safe) {
     2         if (!mQuitAllowed) {
     3             throw new IllegalStateException("Main thread not allowed to quit.");
     4         }
     5 
     6         synchronized (this) {
     7             if (mQuitting) {
     8                 return;
     9             }
    10             mQuitting = true;
    11 
    12             if (safe) {
    13                 removeAllFutureMessagesLocked();
    14             } else {
    15                 removeAllMessagesLocked();
    16             }
    17 
    18             // We can assume mPtr != 0 because mQuitting was previously false.
    19             nativeWake(mPtr);
    20         }
    21     }

    ThreadPoolExecutor

    优点:

    1. 重用线程池中的线程,避免因为线程的原因和销毁所带来的性能消耗;
    2. 能有效控制线程池的并发数,避免资源抢占导致的阻塞现象。

    看下ThreadPoolExecutor的构造方法:

    1 public ThreadPoolExecutor(int corePoolSize,
    2                           int maximumPoolSize,
    3                           long keepAliveTime,
    4                           TimeUnit unit,
    5                           BlockingQueue<Runnable> workQueue,
    6                           ThreadFactory threadFactory,
    7                           RejectedExecutionHandler handler)

    corePoolSize:核心线程池数,默认情况一直存活,即使是闲置状态。
    maximumPoolSize:最大线程数,如果超出这个值,就会阻塞。
    keepAliveTime:超时时长。超过非核心线程就会被回收。
    unit:keepAliveTime的时间单位,(TimeUnit.SECOND,TimeUnit.MILLISECONDS,TimeUnit.MINUTES)。
    workQueue:任务队列,execute方法提交的Runnable对象存在这个参数里面。
    threadFactory:线程工程,为线程提供新线程的功能。

    先贴个以前写线程池这块的工具类:

      1 import java.util.concurrent.ExecutorService;
      2 import java.util.concurrent.Executors;
      3 import java.util.concurrent.Future;
      4 import java.util.concurrent.ScheduledExecutorService;
      5 import java.util.concurrent.TimeUnit;
      6 
      7 /**
      8  * @类名: ThreadUtils
      9  * @描述: TODO(线程池工具类)
     10  * @作者: soyoungboy
     11  */
     12 public class ThreadUtils {
     13     /**
     14      * 单线程
     15      */
     16     static ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
     17     private static volatile ThreadUtils instance = null;
     18     /**
     19      * 初始化的线程数,有待历史的验证,暂时弄4个
     20      */
     21     public ExecutorService threadPool = Executors.newFixedThreadPool(4);
     22     /**
     23      * 执行延迟任务,类似Timer的效果
     24      */
     25     public ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(2);
     26 
     27     // private constructor suppresses
     28     private ThreadUtils() {
     29 
     30     }
     31 
     32     public static ThreadUtils getInstance() {
     33         // if already inited, no need to get lock everytime
     34         if (instance == null) {
     35             synchronized (ThreadUtils.class) {
     36                 if (instance == null) {
     37                     instance = new ThreadUtils();
     38                 }
     39             }
     40         }
     41 
     42         return instance;
     43     }
     44 
     45     /**
     46      * 立即执行任务
     47      *
     48      * @param task ThreadUtils.getInstance().excute(run);
     49      */
     50     public void excute(Runnable task) {
     51         threadPool.execute(task);
     52     }
     53 
     54     /**
     55      * 单线程持操作,主要用于数据库的读写异步操作
     56      *
     57      * @param task ThreadUtils.getInstance().excuteSingleThread(run);
     58      * @return
     59      */
     60     public Future excuteSingleThread(Runnable task) {
     61         return singleThreadPool.submit(task);
     62     }
     63 
     64     ;
     65 
     66     /**
     67      * 延后执行任务
     68      *
     69      * @param task
     70      * @param delay ThreadUtils.getInstance().schedule(run,1000);
     71      */
     72     public void schedule(Runnable task, long delay) {
     73         scheduleThreadPool.schedule(task, delay, TimeUnit.MILLISECONDS);
     74     }
     75 
     76     public Future execuse(final Task task) {
     77         task.onstart();
     78         Future future = excuteSingleThread(new Runnable() {
     79             @Override
     80             public void run() {
     81                 try {
     82                     task.doInBackground();
     83                 } catch (Exception e) {
     84                     task.transfer(null, Task.TRANSFER_DOERROR);
     85                     return;
     86                 }
     87                 task.transfer(null, Task.TRANSFER_DOUI);
     88             }
     89         });
     90         return future;
     91     }
     92 
     93 
     94     /**
     95      * @param 设定文件
     96      * @return void 返回类型
     97      * @throws 在onDestory ()中执行[ThreadUtils.getInstance().shutdownThreadPool()]
     98      * @Title: shutdownThreadPool
     99      * @Description: TODO()
    100      */
    101     public void shutdownThreadPool() {
    102         threadPool.shutdownNow();
    103     }
    104 
    105     /**
    106      * @param 设定文件
    107      * @return void 返回类型
    108      * @throws 在onDestory ()中执行[ThreadUtils.getInstance().shutdownScheduleThreadPool()]
    109      * @Title: shutdownThreadPool
    110      * @Description: TODO()
    111      */
    112     public void shutdownScheduleThreadPool() {
    113         scheduleThreadPool.shutdownNow();
    114 
    115     }
    116 
    117     /**
    118      * @param 设定文件
    119      * @return void 返回类型
    120      * @throws 在onDestory ()中执行[ThreadUtils.getInstance().shutdownSingleThreadPool()]
    121      * @Title: shutdownSingleThreadPool
    122      * @Description: TODO(单线程池销毁操作)
    123      */
    124     public void shutdownSingleThreadPool() {
    125         singleThreadPool.shutdownNow();
    126     }
    127 }

    ThreadPoolExecutor是线程的真正实现;

    线程池的分类:

    1,FixedThreadPool

    FixedThreadPool 线程数量固定的线程池,例如上面代码中如下字段:

     1 public ExecutorService threadPool = Executors.newFixedThreadPool(4) 

    线程数量固定为4,线程空闲不回回收,除非线程关闭。

    2,CacheThreadPool

    线程数量不固定的线程池,最大线程数为Int最大值。

    3,scheduledThreadPool

    核心线程数固定,非核心线程不固定,闲置时非核心线程会立刻被回收,执行定时任务和具有固定周期的重复任务。

     /**
         * 执行延迟任务,类似Timer的效果
         */
        public ScheduledExecutorService scheduleThreadPool = Executors.newScheduledThreadPool(2);

    使用如下:

      /**
         * 延后执行任务
         *
         * @param task
         * @param delay ThreadUtils.getInstance().schedule(run,1000);
         */
        public void schedule(Runnable task, long delay) {
            scheduleThreadPool.schedule(task, delay, TimeUnit.MILLISECONDS);
        }

    4,SingleThreadExcutor

    SingleThreadExcutor单线程池,只有一个核心线程,所有任务再同一线程中按序执行,不回存在线程同步问题。

    声明:

     /**
         * 单线程
         */
        static ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();

    使用:

    /**
         * 单线程持操作,主要用于数据库的读写异步操作
         *
         * @param task ThreadUtils.getInstance().excuteSingleThread(run);
         * @return
         */
        public Future excuteSingleThread(Runnable task) {
            return singleThreadPool.submit(task);
        }
    
        

     

    IntentService:

    IntentService是继承自service并异步处理耗时操作,当任务执行完毕,自动停止。可以启动多次,耗时操作在IntentService的onHandIntent中进行,所有请求都在单一线程中,并且每次只执行一个异步任务。

    IntentService的优点:

    1. 不用手动在service中创建线程;
    2. 操作完成后不用手动关闭service。

    首先贴下IntentService的源码,很短:

    /**
     * IntentService is a base class for {@link Service}s that handle asynchronous
     * requests (expressed as {@link Intent}s) on demand.  Clients send requests
     * through {@link android.content.Context#startService(Intent)} calls; the
     * service is started as needed, handles each Intent in turn using a worker
     * thread, and stops itself when it runs out of work.
     *
     * <p>This "work queue processor" pattern is commonly used to offload tasks
     * from an application's main thread.  The IntentService class exists to
     * simplify this pattern and take care of the mechanics.  To use it, extend
     * IntentService and implement {@link #onHandleIntent(Intent)}.  IntentService
     * will receive the Intents, launch a worker thread, and stop the service as
     * appropriate.
     *
     * <p>All requests are handled on a single worker thread -- they may take as
     * long as necessary (and will not block the application's main loop), but
     * only one request will be processed at a time.
     *
     * <div class="special reference">
     * <h3>Developer Guides</h3>
     * <p>For a detailed discussion about how to create services, read the
     * <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p>
     * </div>
     *
     * @see android.os.AsyncTask
     */
    public abstract class IntentService extends Service {
        private volatile Looper mServiceLooper;
        private volatile ServiceHandler mServiceHandler;
        private String mName;
        private boolean mRedelivery;
    
        private final class ServiceHandler extends Handler {
            public ServiceHandler(Looper looper) {
                super(looper);
            }
    
            @Override
            public void handleMessage(Message msg) {
            //调用onHandleIntent
            //调用stopSelf自动关闭Service
    onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } }
    /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public IntentService(String name) { super(); mName = name; } /** * Sets intent redelivery preferences. Usually called from the constructor * with your preferred semantics. * * <p>If enabled is true, * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_REDELIVER_INTENT}, so if this process dies before * {@link #onHandleIntent(Intent)} returns, the process will be restarted * and the intent redelivered. If multiple Intents have been sent, only * the most recent one is guaranteed to be redelivered. * * <p>If enabled is false (the default), * {@link #onStartCommand(Intent, int, int)} will return * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent * dies along with it.
       *设置当进程被重建时是否需要重新接受意图,true表示需要,并且当有多个意图时,只能保证最近的一个可以收到。
    */ public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @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.      //HandlerThread是集成自Thread的子类,与ServiceHandler进行关联 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); } /** * You should not override this method for your IntentService. Instead, * override {@link #onHandleIntent}, which the system calls when the IntentService * receives a start request. * @see android.app.Service#onStartCommand
       *这个不重写,主要重写onHandleIntent
    */ @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { mServiceLooper.quit(); } /** * Unless you provide binding for your service, you don't need to implement this * method, because the default implementation returns null. * @see android.app.Service#onBind */ @Override @Nullable public IBinder onBind(Intent intent) { return null; } /** * This method is invoked on the worker thread with a request to process. * Only one Intent is processed at a time, but the processing happens on a * worker thread that runs independently from other application logic. * So, if this code takes a long time, it will hold up other requests to * the same IntentService, but it will not hold up anything else. * When all requests have been handled, the IntentService stops itself, * so you should not call {@link #stopSelf}. * * @param intent The value passed to {@link * android.content.Context#startService(Intent)}. * This may be null if the service is being restarted after * its process has gone away; see * {@link android.app.Service#onStartCommand} * for details. */ @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent); }

    继承自Service,在异步线程处理任务,通过startService启动,当任务完成会自动停止,不用手动处理,耗时任务会以队列形式在onHandleIntent中依次执行,然后结束。

    oncreate()中创建并执行HandlerThread,也就是实现对MessageQqueue队列的循环遍历操作,将消息分发给Handler的handlerMessage方法 。

    onStartCommand()调用onStart,发消息并由ServiceHandler的handleMessage来进行处理。

    IntentService启动了线程里面带有Looper的线程,具有消息处理的能力,最后通过onHandleIntent()来处理,执行完后通过stopSelf()来停掉自己。

    onHandleIntent抽象方法,需要子类实现。

    1 onHandleIntent((Intent)msg.obj);
    2 stopSelf(msg.arg1);
  • 相关阅读:
    pta-L2-032 彩虹瓶 (25 分)
    pat-L2-019 悄悄关注
    谷歌与Airbnb的JS代码规范
    无阻塞加载脚本----性能优化(二)
    web开发者性能优化工具(一)
    threeJS创建mesh,创建平面,设置mesh的平移,旋转、缩放、自传、透明度、拉伸
    攻防世界-web-高手进阶区011-Web_python_template_injection
    攻防世界-web-高手进阶区010-upload1
    攻防世界-web-高手进阶区009-unserialize3
    攻防世界-web-高手进阶区008-PHP2
  • 原文地址:https://www.cnblogs.com/androidsuperman/p/6274963.html
Copyright © 2011-2022 走看看