1. Handler
- 可以定时执行Message&MessageQueue
- 在不同线程中执行
A Handler allows you to send and process Message
and Runnable objects associated with a thread's MessageQueue
. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
Scheduling messages is accomplished with the
post(Runnable)
,postAtTime(Runnable, long)
,postDelayed(Runnable, long)
,sendEmptyMessage(int)
,sendMessage(Message)
,sendMessageAtTime(Message, long)
, andsendMessageDelayed(Message, long)
methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue aMessage
object containing a bundle of data that will be processed by the Handler'shandleMessage(Message)
method (requiring that you implement a subclass of Handler).When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-based behavior.
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate.
(1). Message
Defines a message containing a description and arbitrary data object that can be sent to a
Handler
. This object contains two extra int fields and an extra object field that allow you to not do allocations in many cases.
(2).MessageQueue
Low-level class holding the list of messages to be dispatched by a
Looper
. Messages are not added directly to a MessageQueue, but rather throughHandler
objects associated with the Looper.You can retrieve the MessageQueue for the current thread with
Looper.myQueue()
.
- Message的队列
- 每个线程最多只能拥有一个
- Thread-->Looper-->MessageQueue
(3).Looper
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call
prepare()
in the thread that is to run the loop, and thenloop()
to have it process messages until the loop is stopped.Most interaction with a message loop is through the
Handler
class.
- Looper从MessageQueue中取出Message
- 交由Handler的HandlerMessage处理
- 调用Message.recycle将其放入Message Pool中
2.Service
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding <service>
declaration in its package'sAndroidManifest.xml
. Services can be started with Context.startService()
and Context.bindService()
.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService
class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.
- A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
- A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
Thus a Service itself is actually very simple, providing two main features:
- A facility for the application to tell the system about something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to
Context.startService()
, which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it. - A facility for an application to expose some of its functionality to other applications. This corresponds to calls to
Context.bindService()
, which allows a long-standing connection to be made to the service in order to interact with it.
(1).Service Lifecycle
There are two reasons that a service can be run by the system. If someone calls
Context.startService()
then the system will retrieve the service (creating it and calling itsonCreate()
method if needed) and then call itsonStartCommand(Intent, int, int)
method with the arguments supplied by the client. The service will at this point continue running untilContext.stopService()
orstopSelf()
is called. Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called; however, services can use theirstopSelf(int)
method to ensure the service is not stopped until started intents have been processed.For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand():
START_STICKY
is used for services that are explicitly started and stopped as needed, whileSTART_NOT_STICKY
orSTART_REDELIVER_INTENT
are used for services that should only remain running while processing any commands sent to them. See the linked documentation for more detail on the semantics.Clients can also use
Context.bindService()
to obtain a persistent connection to a service. This likewise creates the service if it is not already running (callingonCreate()
while doing so), but does not call onStartCommand(). The client will receive theIBinder
object that the service returns from itsonBind(Intent)
method, allowing the client to then make calls back to the service. The service will remain running as long as the connection is established (whether or not the client retains a reference on the service's IBinder). Usually the IBinder returned is for a complex interface that has beenwritten in aidl.A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started orthere are one or more connections to it with the
Context.BIND_AUTO_CREATE
flag. Once neither of these situations hold, the service'sonDestroy()
method is called and the service is effectively terminated. All cleanup (stopping threads, unregistering receivers) should be complete upon returning from onDestroy().(2).Permissions
Global access to a service can be enforced when it is declared in its manifest's
<service>
tag. By doing so, other applications will need to declare a corresponding<uses-permission>
element in their own manifest to be able to start, stop, or bind to the service.As of
GINGERBREAD
, when usingContext.startService(Intent)
, you can also setIntent.FLAG_GRANT_READ_URI_PERMISSION
and/orIntent.FLAG_GRANT_WRITE_URI_PERMISSION
on the Intent. This will grant the Service temporary access to the specific URIs in the Intent. Access will remain until the Service has calledstopSelf(int)
for that start command or a later one, or until the Service has been completely stopped. This works for granting access to the other apps that have not requested the permission protecting the Service, or even when the Service is not exported at all.In addition, a service can protect individual IPC calls into it with permissions, by calling the
checkCallingPermission(String)
method before executing the implementation of that call.
3.BroadCastReceiver
Base class for code that will receive intents sent by sendBroadcast().
If you don't need to send broadcasts across applications, consider using this class with LocalBroadcastManager
instead of the more general facilities described below. This will give you a much more efficient implementation (no cross-process communication needed) and allow you to avoid thinking about any security issues related to other applications being able to receive or send your broadcasts.
You can either dynamically register an instance of this class with Context.registerReceiver()
or statically publish an implementation through the<receiver>
tag in your AndroidManifest.xml
.
Note: If registering a receiver in your Activity.onResume()
implementation, you should unregister it in Activity.onPause()
. (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState()
, because this won't be called if the user moves back in the history stack.
There are two major classes of broadcasts that can be received:
- Normal broadcasts (sent with
Context.sendBroadcast
) are completely asynchronous. All receivers of the broadcast are run in an undefined order, often at the same time. This is more efficient, but means that receivers cannot use the result or abort APIs included here. - Ordered broadcasts (sent with
Context.sendOrderedBroadcast
) are delivered to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won't be passed to other receivers. The order receivers run in can be controlled with theandroid:priority
attribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.
Even in the case of normal broadcasts, the system may in some situations revert to delivering the broadcast one receiver at a time. In particular, for receivers that may require the creation of a process, only one will be run at a time to avoid overloading the system with new processes. In this situation, however, the non-ordered semantics hold: these receivers still cannot return results or abort their broadcast.
Note that, although the Intent class is used for sending and receiving these broadcasts, the Intent broadcast mechanism here is completely separate from Intents that are used to start Activities with Context.startActivity()
. There is no way for a BroadcastReceiver to see or capture Intents used with startActivity(); likewise, when you broadcast an Intent, you will never find or start an Activity. These two operations are semantically very different: starting an Activity with an Intent is a foreground operation that modifies what the user is currently interacting with; broadcasting an Intent is a background operation that the user is not normally aware of.
(1).Security
Receivers used with the
Context
APIs are by their nature a cross-application facility, so you must consider how other applications may be able to abuse your use of them. Some things to consider are:The Intent namespace is global. Make sure that Intent action names and other strings are written in a namespace you own, or else you may inadvertently conflict with other applications.
When you use
registerReceiver(BroadcastReceiver, IntentFilter)
, any application may send broadcasts to that registered receiver. You can control who can send broadcasts to it through permissions described below.When you publish a receiver in your application's manifest and specify intent-filters for it, any other application can send broadcasts to it regardless of the filters you specify. To prevent others from sending to it, make it unavailable to them with
android:exported="false"
.When you use
sendBroadcast(Intent)
or related methods, normally any other application can receive these broadcasts. You can control who can receive such broadcasts through permissions described below. Alternatively, starting withICE_CREAM_SANDWICH
, you can also safely restrict the broadcast to a single application withIntent.setPackage
None of these issues exist when using
LocalBroadcastManager
, since intents broadcast it never go outside of the current process.Access permissions can be enforced by either the sender or receiver of a broadcast.
To enforce a permission when sending, you supply a non-null permission argument to
sendBroadcast(Intent, String)
orsendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)
. Only receivers who have been granted this permission (by requesting it with the<uses-permission>
tag in theirAndroidManifest.xml
) will be able to receive the broadcast.
To enforce a permission when receiving, you supply a non-null permission when registering your receiver -- either when calling
registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)
or in the static<receiver>
tag in yourAndroidManifest.xml
. Only broadcasters who have been granted this permission (by requesting it with the<uses-permission>
tag in theirAndroidManifest.xml
) will be able to send an Intent to the receiver.
(2).Receiver Lifecycle
A BroadcastReceiver object is only valid for the duration of the call to
onReceive(Context, Intent)
. Once your code returns from this function, the system considers the object to be finished and no longer active.This has important repercussions to what you can do in an
onReceive(Context, Intent)
implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the
NotificationManager
API. For the latter, you can useContext.startService()
to send a command to the service.
(3).Process Lifecycle
A process that is currently executing a BroadcastReceiver (that is, currently running the code in its
onReceive(Context, Intent)
method) is considered to be a foreground process and will be kept running by the system except under cases of extreme memory pressure.Once you return from onReceive(), the BroadcastReceiver is no longer active, and its hosting process is only as important as any other application components that are running in it. This is especially important because if that process was only hosting the BroadcastReceiver (a common case for applications that the user has never or not recently interacted with), then upon returning from onReceive() the system will consider its process to be empty and aggressively kill it so that resources are available for other more important processes.
This means that for longer-running operations you will often use a
Service
in conjunction with a BroadcastReceiver to keep the containing process active for the entire time of your operation.