android--线程

  1. 云栖社区>
  2. 博客>
  3. 正文

android--线程

西北野狼 2017-01-11 19:46:00 浏览648
展开阅读全文

进程优先级

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);

 

网友评论

登录后评论
0/500
评论
西北野狼
+ 关注