BroadcastReceiver处理耗时操作
2012-07-23 14:38
330 查看
Long-Running Receivers and Services
So far, we have covered the happy path of broadcast receivers w here the execution of a
broadcast receiver is unlikely to take more than ten seconds.
As it turns out, the
problem space becomes a bit complicated if we want to perform tasks that take longer than ten seconds.
To understand why, let’s quickly review a few facts about broadcast receivers:
A broadcast receiver, like other components of an An droid process,
runs on the main thread.
Holding up the code in a broadcast receiver will hold up the main
thread and will result in ANR.
The time limit on a broadcast receiver is ten seconds compared to five
seconds for an activity. It is a touch of a reprieve, but the limit is still
there.
The process hosting the broadcast receiver will start and terminate
along with the broadcast receiver execution. Hence the process will
not stick around after the broadcast receiver’s onReceive() method
returns. Of course, this is assumi ng that the process contains only the
broadcast receiver. If the process contains other components, such as
activities or services, that are alr eady running, then the lifetime of the
process takes these component life cycles into account as well.
Unlike a service process, a broadcast receiver process will not get restarted.
If a broadcast receiver were to start a separate thread and return to
the main thread, Android will assume that the work is complete and
will shut down the process even if there are threads running, bringing
those threads to abrupt stop.
Android acquires a partial wake lock when invoking a broadcast
service and releases it when it re turns from the service in the main
thread. A wake lock is a mechanism and an API class available in the
SDK to keep the device from going to sleep or wake it up if it is already asleep.
Given these predicates, how can we ex ecute longer-running code in response to a
broadcast event?
Long-Running Broadcast Receiver Protocol
The answer lies in resolving the following:
We will clearly need a separate thread so that the main thread can get
back and avoid ANR messages.
To stop Android from killing the process and hence the worker thread,
we need to tell Android that this process contains a component, such
as a service, with a life cycle. So we need to create or start that
service. The service itself cannot directly do the work for more than
five seconds because that happens on the main thread, so the service
needs to start a worker thread and let the main thread go.
For the duration of the worker thread’s execution, we need to hold on
to the partial wake lock so that the device won’t go to sleep. A partial
wake lock will allow the device to run code without turning on the
screen and so on, which allows for longer battery life.
The partial wake lock must be obtained in the main line code of the
receiver; otherwise, it will be too late. For example, you cannot do this
in the service, because it may be too late between the startService()
being issued by the broadcast receiver and the onStartCommand() of a
service that begins execution.
Because we are creating a service, the service itself can be brought
down and brought back up because of low-memory conditions. If this
happens, we need to acquire the wake lock again.
When the worker thread started by the onStartCommand() method of
the service completes its work, it needs to tell the service to stop so
that it can be put to bed and not brought back to life by Android.
It is also possible that more than one broadcast event can occur.
Given that, we need to be cautious about how many worker threads
we need to spawn.
Given these facts, the recommended protocol for extending the life of a broadcast
receiver is as follows:
1. Get a (static) partial wake lock in the onReceive() method of the
broadcast receiver. The partial wake lock needs to be static to allow
communication between the broadcast receiver and the service. There
is no other way of passing a reference of the wake lock to the service,
as the service is invoked through a default constructor that takes no
parameters.
2. Start a local service so that the process won’t be killed.
CHAPTER 19: Broadcast Receivers and Long-Running Services 516
3. In the service, start a worker thread to do the work. Do not do the work
in the onStart() method of the service. If you do, you are basically
holding up the main thread again.
4. When the worker thread is done, tell the service to stop itself either
directly or through a handler.
5. Have the service turn off the static wake lock. To repeat, a static wake
lock is the only way to communicate between a service and its invoker,
in this case the broadcast service, because there is no way to pass a
wake lock reference to the service.
You can read the book for more info, the following is an example:
So far, we have covered the happy path of broadcast receivers w here the execution of a
broadcast receiver is unlikely to take more than ten seconds.
As it turns out, the
problem space becomes a bit complicated if we want to perform tasks that take longer than ten seconds.
To understand why, let’s quickly review a few facts about broadcast receivers:
A broadcast receiver, like other components of an An droid process,
runs on the main thread.
Holding up the code in a broadcast receiver will hold up the main
thread and will result in ANR.
The time limit on a broadcast receiver is ten seconds compared to five
seconds for an activity. It is a touch of a reprieve, but the limit is still
there.
The process hosting the broadcast receiver will start and terminate
along with the broadcast receiver execution. Hence the process will
not stick around after the broadcast receiver’s onReceive() method
returns. Of course, this is assumi ng that the process contains only the
broadcast receiver. If the process contains other components, such as
activities or services, that are alr eady running, then the lifetime of the
process takes these component life cycles into account as well.
Unlike a service process, a broadcast receiver process will not get restarted.
If a broadcast receiver were to start a separate thread and return to
the main thread, Android will assume that the work is complete and
will shut down the process even if there are threads running, bringing
those threads to abrupt stop.
Android acquires a partial wake lock when invoking a broadcast
service and releases it when it re turns from the service in the main
thread. A wake lock is a mechanism and an API class available in the
SDK to keep the device from going to sleep or wake it up if it is already asleep.
Given these predicates, how can we ex ecute longer-running code in response to a
broadcast event?
Long-Running Broadcast Receiver Protocol
The answer lies in resolving the following:
We will clearly need a separate thread so that the main thread can get
back and avoid ANR messages.
To stop Android from killing the process and hence the worker thread,
we need to tell Android that this process contains a component, such
as a service, with a life cycle. So we need to create or start that
service. The service itself cannot directly do the work for more than
five seconds because that happens on the main thread, so the service
needs to start a worker thread and let the main thread go.
For the duration of the worker thread’s execution, we need to hold on
to the partial wake lock so that the device won’t go to sleep. A partial
wake lock will allow the device to run code without turning on the
screen and so on, which allows for longer battery life.
The partial wake lock must be obtained in the main line code of the
receiver; otherwise, it will be too late. For example, you cannot do this
in the service, because it may be too late between the startService()
being issued by the broadcast receiver and the onStartCommand() of a
service that begins execution.
Because we are creating a service, the service itself can be brought
down and brought back up because of low-memory conditions. If this
happens, we need to acquire the wake lock again.
When the worker thread started by the onStartCommand() method of
the service completes its work, it needs to tell the service to stop so
that it can be put to bed and not brought back to life by Android.
It is also possible that more than one broadcast event can occur.
Given that, we need to be cautious about how many worker threads
we need to spawn.
Given these facts, the recommended protocol for extending the life of a broadcast
receiver is as follows:
1. Get a (static) partial wake lock in the onReceive() method of the
broadcast receiver. The partial wake lock needs to be static to allow
communication between the broadcast receiver and the service. There
is no other way of passing a reference of the wake lock to the service,
as the service is invoked through a default constructor that takes no
parameters.
2. Start a local service so that the process won’t be killed.
CHAPTER 19: Broadcast Receivers and Long-Running Services 516
3. In the service, start a worker thread to do the work. Do not do the work
in the onStart() method of the service. If you do, you are basically
holding up the main thread again.
4. When the worker thread is done, tell the service to stop itself either
directly or through a handler.
5. Have the service turn off the static wake lock. To repeat, a static wake
lock is the only way to communicate between a service and its invoker,
in this case the broadcast service, because there is no way to pass a
wake lock reference to the service.
You can read the book for more info, the following is an example:
public abstract class ALongRunningNonStickyBroadcastService extends IntentService { public static String tag = "ALongRunningBroadcastService"; protected abstract void handleBroadcastIntent(Intent broadcastIntent); public ALongRunningNonStickyBroadcastService(String name){ super(name); } /* * This method can be invoked under two circumstances * 1. When a broadcast receiver issues a "startService" * 2. when android restarts it due to pending "startService" intents. * * In case 1, the broadcast receiver has already * setup the "lightedgreenroom". * * In case 2, we need to do the same. */ @Override public void onCreate() { super.onCreate(); //Set up the green room //The setup is capable of getting called multiple times. LightedGreenRoom.setup(this.getApplicationContext()); //It is possible that more than one service //of this type is running. //Knowing the number will allow us to clean up //the locks in ondestroy. LightedGreenRoom.s_registerClient(); } @Override public int onStartCommand(Intent intent, int flag, int startId) { //Call the IntentService "onstart" super.onStart(intent, startId); //Tell the green room there is a visitor LightedGreenRoom.s_enter(); //mark this as non sticky //Means: Don't restart the service if there are no //pending intents. return Service.START_NOT_STICKY; } /* * Note that this method call runs * in a secondary thread setup by the IntentService. * * Override this method from IntentService. * Retrieve the original broadcast intent. * Call the derived class to handle the broadcast intent. * finally tell the lighted room that you are leaving. * if this is the last visitor then the lock * will be released. */ @Override final protected void onHandleIntent(Intent intent) { try { Intent broadcastIntent = intent.getParcelableExtra("original_intent"); handleBroadcastIntent(broadcastIntent); } finally { LightedGreenRoom.s_leave(); } } /* * If Android reclaims this process, * this method will release the lock * irrespective of how many visitors there are. */ @Override public void onDestroy() { super.onDestroy(); LightedGreenRoom.s_unRegisterClient(); } }
相关文章推荐
- 如何在 BroadcastReceiver 中执行耗时操作?
- BroadCastReceiver中耗时操作导致ANR
- BroadCastReceiver中耗时操作导致ANR
- android 直接在activity/broadcast receiver中启动子线程来处理长时间的耗时任务不行吗?
- android中的broadcastreceiver不可以做耗时操作
- 关于耗时操作的处理方式猜想/我所用到的队列操作
- BroadcastReceiver 使用goAsync 执行异步操作
- 回调 处理耗时操作
- android开发 用线程进行耗时操作,统一处理 第二版
- 利用IntentService实现在broadcastreceiver中比较耗时的任务
- Activity、BroadcastReceiver、Service,只要是有长时间处理的任务,就需要重新开一个线程?!
- 在 .NET Web 开发中,使用 ThreadPool.QueueUserWorkItem 异步地处理耗时操作
- ProcessDialog结合Thread处理耗时操作(Handler和Thread)
- 开一个线程来处理 耗时的操作
- ProcessDialog结合Thread处理耗时操作
- iOS开发创建UI的耗时操作处理
- UI系统中的耗时操作处理
- django 耗时操作处理办法 celery
- android 的Handler处理UI主线程外的耗时操作
- Swing 代码演示: 用户操作引发的耗时任务的处理方式