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 }