IntentService和HandlerThread 使用与区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_17338093/article/details/81287982

1:IntentService介绍和IntentService与Server的区别;

2:HandlerThread的介绍;

3:IntenetServer的使用;

1:1:IntentService介绍和IntentService与Server的区别;

/**
 * IntentService 介绍
 * IntentService 是一种特殊的 Service,它继承了 Service 并且它是一个抽象类,因此必须创建它的子类才能够使用 IntentService。
 * 它可用于执行后台耗时任务,当任务执行完成后它会自动停止,在资源不足时,系统会对一些被认为时无用的资源给清理掉,
 * 由于它是 Service 的原因,它的优先级比单纯的线程的优先级高很多,不容易被系统杀死(清理掉),所以它适合执行一些高优先级的后台任务。
 * 在实现上,IntentService 封装了 Handlerhread 和 Handler。
 * 另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,
 * 并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
 */

/**
 * InteneServer和Server的区别(来源:https://blog.csdn.net/mp624183768/article/details/54882965):
 * 1:Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR,为了解决这样的问题,引入了IntentService;
 * 2:IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期。
 * 那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去执行耗时操作
 * IntentService:异步处理服务,新开一个线程:handlerThread在线程中发消息,然后接受处理完成后,会清理线程,并且关掉服务。
 * IntentService有以下特点:
 (1)  它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents。
 (2)  创建了一个工作队列,来逐个发送intent给onHandleIntent()。
 (3)  不需要主动调用stopSelft()来结束服务。因为,在所有的intent被处理完后,系统会自动关闭服务。
 (4)  默认实现的onBind()返回null
 (5)  默认实现的onStartCommand()的目的是将intent插入到工作队列中
 */
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((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;//构造时,传入我们创建的IntentServer的名字
        /**
         * IntentServer生命周期
         * 1:onCreate()初始化HandlerThread和ServiceHandler,用于在后面调用onStart后来发送消息
         * 2:每次启动服务都会调用一次onStartCommand()方法,并且它会调用onStart()
         * 3:在onStart()中发送消息
         */
    }

    /**
     * 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.
     */
    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.
        //onCreate被执行时内部会开启一个线程和创建一个消息队列,用于解决在后台服务中进行的耗时操作;
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();//创建队列,获取looper对象
        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
     */
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        /**
         * {@link mRedelivery }会根据setIntentRedelivery()设置的布尔值返回START_REDELIVER_INTENT or START_NOT_STICKY;
         * START_NOT_STICKY:服务会直接被关闭,当我们的操作不是十分重要的时候,我们可以选择START_NOT_STICKY,这也是IntentService的默认选项
         * START_REDELIVER_INTENT :服务会在可用资源不再吃紧的时候尝试再次启动服务,当我们认为操作十分重要时,则应该选择START_REDELIVER_INTENT 型服务
         */
        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);
}

HandlerThread介绍

/**
 * Handy class for starting a new thread that has a looper. The looper can then be 
 * used to create handler classes. Note that start() must still be called.
 * 它是一种可以使用Handler的Thread,内部对Thread的run()进行重写,它实现是通过在run()方法中通过looper.prepare()来创建消息队列,
 * 并通过Looper.loop()方法来开启消息循环,通过Handler的消息方式(looer循环)来通知HandlerThread执行一个具体的任务;
 */
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    /**
     * Constructs a HandlerThread.
     * @param name
     * @param priority The priority to run the thread at. The value supplied must be from 
     * {@link android.os.Process} and not from java.lang.Thread.
     */
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    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;
    }
    
    /**
     * This method returns the Looper associated with this thread. If this thread not been started
     * or for any reason isAlive() returns false, this method will return null. If this thread
     * has been started, this method will block until the looper has been initialized.  
     * @return The 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;
    }

    /**
     * @return a shared {@link Handler} associated with this thread
     * @hide
     */
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

    /**
     * Quits the handler thread's looper.
     * <p>
     * Causes the handler thread's looper to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     * 使用此方法可能是不安全的,因为在looper队列终止之前可能无法传递某些信息
     * @see #quitSafely
     */
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

    /**
     * Quits the handler thread's looper safely.
     * <p>
     * Causes the handler thread's looper to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * Pending delayed messages with due times in the future will not be delivered.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p>
     * If the thread has not been started or has finished (that is if
     * {@link #getLooper} returns null), then false is returned.
     * Otherwise the looper is asked to quit and true is returned.
     * </p>
     * 使用此方法可能是安全的,因为一旦已经传递消息,队列中的所有剩余消息被处理,方法就会终止,然而,
     * 在循环终止之前,延迟的消息将在未来到期时间内不传递
     * @return True if the looper looper has been asked to quit or false if the
     * thread had not yet started running.
     */
    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}
IntentService使用:
/**
 * 1:需要在mainfest中注册服务;<service android:name=".IntentServerDemo"/>
 * 2: Intent intent = new Intent(MainActivity.this, IntentServerDemo.class);
        intent.putExtra("action","TASK1"); startService(intent);
 */
public class IntentServerDemo extends IntentService{

    /**
     * Error:has no zero argument constructor
     */
    public IntentServerDemo(){
        super("");
    }
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentServerDemo(String name) {
        super(name);
        Log.i("bugtags",">>>IntentServerDemo=="+name);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("bugtags",">>>onCreate");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.i("bugtags",">>>onHandleIntent="+intent.getStringExtra("action"));
        SystemClock.sleep(5000);
    }

    @Override
    public void onDestroy() {
        Log.i("bugtags",">>>onDestroy");
        super.onDestroy();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_17338093/article/details/81287982