Shocked, what you think of as Service is what you think of as Service

Service Science Popularization

Do you always think that Service runs in sub-threads? So this article is to hit your face, running in the background does not mean running in the sub-thread. Again, I repeat aloud that Service runs in the main thread.

I know you don't want to believe, can't believe, don't want to believe, in the heart of thousands of grass and mud horses galloping past. Bedroom, why is the front desk not blocked? Why is there no ANR? Why......
Because you didn't do time-consuming operations. (Although you're a fool, Dad still loves you (())

So what if there are time-consuming operations?
Fool, the opening thread processing is not good. Just use Handler Thread.
Wouldn't I have to rewrite a bunch of code?
My dear dumb, ready-made IntentService can solve your problem, as long as the simple implementation of onHandle Intent.
My dear father, tell me how to use it.
Well, my dear son. Dad first gives you a thread (the story here only knows people know), and then teaches you how to use it properly.

HandlerThread

This is a Thread that uses Handler. If it's the one before me Record a Handler Optimizer Friends familiar with the article may easily understand why.

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();// Note that by preparing in the sub-thread, you can set up the message loop mechanism for the sub-thread.
        synchronized (this) {
            mLooper = Looper.myLooper();// Get the Loper object of the current thread
            notifyAll();// Release the thread in the waiting queue (that is, the main thread), which enters the lock pool state
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();// Preparations can be made before the message loop opens
        Looper.loop();// Start the message loop
        mTid = -1;
    }

As long as the outside world sends messages through Handler, it can let Handler Thread perform a specific task.

IntentService

We can note that the header comment of IntentService reads as follows:

 * 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.

That is to say, IntentService uses the work queue processor model, which is usually used to perform background tasks. The simplest way to use it is to inherit and override the onHandleIntent method and stop at the appropriate time.
At the same time, IntentService is a service, suitable for performing some high priority tasks, not easy to be killed by the system, which is incomparable with a simple thread.

Next, let's unveil its mystery.

    @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 + "]");// Instantiate a Handler Thread
        thread.start();// Threads ready to run, waiting for CPU scheduling

        mServiceLooper = thread.getLooper();// The getLooper method causes the main thread to abandon the lock tag of the object and enter the waiting queue through the wait of the critical resource until the mLooper initialization in HandlerThread completes calling notifyAll to release the main thread.
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

We noticed that the last step was to associate the Loper object of the subthread into Service Handler, so what happened in Service Handler?

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);// Connecting our current worker thread Handler Thread's Looper circulator to Handler, Handler uses this Looper for message looping
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);// Rewrite onHandleIntent; perform our time-consuming tasks according to Intent
            stopSelf(msg.arg1);// Task execution stops automatically
        }
    }

We know that every time a Service starts, onStartCommand is called, which is the best time to send a message.

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);// Send messages to HandlerThread threads for processing
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();// Stop the message queue loop
    }

Added by eriksmoen on Wed, 17 Jul 2019 00:28:51 +0300