Service官方教程(2)*IntentService与Service示例、onStartCommand()3个返回值的含义。
1.Creating a Started Service
A started service is one that another component starts by calling startService(), resulting in a call to the service's onStartCommand() method.
When a service is started, it has a lifecycle that's independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf(), or another component can stop it by calling stopService().
An application component such as an activity can start the service by calling startService() and passing an Intent that specifies the service and includes any data for the service to use. The service receives this Intent in the onStartCommand() method.
For instance, suppose an activity needs to save some data to an online database. The activity can start a companion service and deliver it the data to save by passing an intent to startService(). The service receives the intent in onStartCommand(), connects to the Internet and performs the database transaction. When the transaction is done, the service stops itself and it is destroyed.
Caution: A service runs in the same process as the application in which it is declared and in the main thread
of that application, by default. So, if your service performs intensive or blocking operations while the user
interacts with an activity from the same application, the service will slow down activity performance. To avoid
impacting application performance, you should start a new thread inside the service.
默认情况下:服务就在定义它的进程的主线程里,如果费时操作要启动个新线程。
android:process="xxx"情况下:创建新进程。
Traditionally, there are two classes you can extend to create a started service:
- This is the base class for all services. When you extend this class, it's important that you create a new thread in which to do all the service's work, because the service uses your application's main thread, by default, which could slow the performance of any activity your application is running.
- This is a subclass of
Servicethat uses a worker thread to handle all start requests, one at a time. This is the best option if you don't require that your service handle multiple requests simultaneously. All you need to do is implementonHandleIntent(), which receives the intent for each start request so you can do the background work.
The following sections describe how you can implement your service using either one for these classes.
2.Extending the IntentService class 启动IntentService示例
Because most started services don't need to handle multiple requests simultaneously (which can actually be a dangerous multi-threading scenario), it's probably best if you implement your service using the IntentService class.
The IntentService does the following:
IntentService类的工作,很方便,如下:
- Creates a default worker thread that executes all intents delivered to
onStartCommand()separate from your application's main thread.创建一个独立线程开始工作。
- Creates a work queue that passes one intent at a time to your
onHandleIntent()implementation, so you never have to worry about multi-threading.创建工作队列,不用担心多线程。
- Stops the service after all start requests have been handled, so you never have to call
stopSelf().自动停止服务,不用手动stopSelf(startId);
- Provides default implementation of
onBind()that returns null.默认onBind()返回null,不用手写。
- Provides a default implementation of
onStartCommand()that sends the intent to the work queue and then to youronHandleIntent()implementation.默认就把intent发送到onHandleIntent方法。
All this adds up to the fact that all you need to do is implement onHandleIntent() to do the work provided by the client. (Though, you also need to provide a small constructor for the service.)
Here's an example implementation of IntentService:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep();
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
}
}
That's all you need: a constructor and an implementation of onHandleIntent().
If you decide to also override other callback methods, such as onCreate(), onStartCommand(), or onDestroy(), be sure to call the super implementation, so that the IntentService can properly handle the life of the worker thread.
For example, onStartCommand() must return the default implementation (which is how the intent gets delivered to onHandleIntent()):
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
Besides onHandleIntent(), the only method from which you don't need to call the super class is onBind() (but you only need to implement that if your service allows binding).
In the next section, you'll see how the same kind of service is implemented when extending the base Service class, which is a lot more code, but which might be appropriate if you need to handle simultaneous start requests.
3.Extending the Service class 启动Service示例
As you saw in the previous section, using IntentService makes your implementation of a started service very simple. If, however, you require your service to perform multi-threading (instead of processing start requests through a work queue), then you can extend the Service class to handle each intent.
For comparison, the following example code is an implementation of the Service class that performs the exact same work as the example above using IntentService. That is, for each start request, it uses a worker thread to perform the job and processes only one request at a time.
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep();
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
@Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
As you can see, it's a lot more work than using IntentService.
However, because you handle each call to onStartCommand() yourself, you can perform multiple requests simultaneously. That's not what this example does, but if that's what you want, then you can create a new thread for each request and run them right away (instead of waiting for the previous request to finish).
Notice that the onStartCommand() method must return an integer. The integer is a value that describes how the system should continue the service in the event that the system kills it (as discussed above, the default implementation for IntentService handles this for you, though you are able to modify it). The return value from onStartCommand() must be one of the following constants:
onStartCommand()返回值只能取下面几个值:
- If the system kills the service after
onStartCommand()returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.在onStartCommand()返回后,如果service被杀死,不重启服务,直到有明确的启动服务的意图。
- If the system kills the service after
onStartCommand()returns, recreate the service and callonStartCommand(), but do not redeliver the last intent. Instead, the system callsonStartCommand()with a null intent, unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.在
onStartCommand()返回后,如果service被杀死,重启服务,并调用一次onStartCommand(),但是这次的Intent是空的,不是结束时的那个.
- If the system kills the service after
onStartCommand()returns, recreate the service and callonStartCommand()with the last intent that was delivered to the service. Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.在
onStartCommand()返回后,如果service被杀死,重启服务,并调用一次onStartCommand(),这个Intent是结束时的那个。
For more details about these return values, see the linked reference documentation for each constant.
4.Starting a Service 启动一个service,永远不要手动调用onStartCommand()
You can start a service from an activity or other application component by passing an Intent (specifying the service to start) to startService(). The Android system calls the service's onStartCommand() method and passes it the Intent. (You should never call onStartCommand() directly.)
For example, an activity can start the example service in the previous section (HelloService) using an explicit intent with startService():
Intent intent = new Intent(this, HelloService.class);
startService(intent);
The startService() method returns immediately and the Android system calls the service's onStartCommand() method. If the service is not already running, the system first calls onCreate(), then calls onStartCommand().
startService()后,时如果Service并没有运行,会先创建一个。
If the service does not also provide binding, the intent delivered with startService() is the only mode of communication between the application component and the service. However, if you want the service to send a result back, then the client that starts the service can create a PendingIntent for a broadcast (with getBroadcast()) and deliver it to the service in the Intent that starts the service. The service can then use the broadcast to deliver a result.
Multiple requests to start the service result in multiple corresponding calls to the service's onStartCommand(). However, only one request to stop the service (with stopSelf() or stopService()) is required to stop it.
Stopping a service 停止一个service
A started service must manage its own lifecycle. That is, the system does not stop or destroy the service unless it must recover system memory and the service continues to run after onStartCommand() returns. So, the service must stop itself by calling stopSelf() or another component can stop it by calling stopService().
除非系统必需释放内存时才会停止或销毁在执行完onCommand()后还在运行的服务。
Once requested to stop with stopSelf() or stopService(), the system destroys the service as soon as possible.
However, if your service handles multiple requests to onStartCommand() concurrently, then you shouldn't stop the service when you're done processing a start request, because you might have since received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can use stopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered to onStartCommand()) to which your stop request corresponds. Then if the service received a new start request before you were able to call stopSelf(int), then the ID will not match and the service will not stop.
停止service有两种方式:
1,service内部 stopSelf(startId);//
2,service外部,其它组件stopService();
Caution: It's important that your application stops its services when it's done working, to avoid wasting system resources and
consuming battery power. If necessary, other components can stop the service by calling stopService().Even if you enable binding
for the service, you must always stop the service yourself if it ever received a call to onStartCommand().
For more information about the lifecycle of a service, see the section below about Managing the Lifecycle of a Service.
Service官方教程(2)*IntentService与Service示例、onStartCommand()3个返回值的含义。的更多相关文章
- Service官方教程(4)两种Service的生命周期函数
Managing the Lifecycle of a Service The lifecycle of a service is much simpler than that of an activ ...
- Service官方教程(11)Bound Service示例之2-AIDL 定义跨进程接口并通信
Android Interface Definition Language (AIDL) 1.In this document Defining an AIDL Interface Create th ...
- Service官方教程(8)Bound Service示例之2-跨进程使用Messenger
Compared to AIDL When you need to perform IPC, using a Messenger for your interface is simpler than ...
- Service官方教程(9)绑定服务时的注意事项
Binding to a Service Application components (clients) can bind to a service by calling bindService() ...
- Service官方教程(6)Bound Services主要用来实现通信服务,以及3种实现通信的方案简介。
1.Bound Services A bound service is the server in a client-server interface. A bound service allows ...
- Service官方教程(5)后台服务发送通知、把服务变前台服务。
1.Sending Notifications to the User (发送通知) Once running, a service can notify the user of events usi ...
- Service官方教程(3)Bound Services
Bound Services 1.In this document The Basics Creating a Bound Service Extending the Binder class Usi ...
- Service官方教程(1)Started与Bound的区别、要实现的函数、声明service
Services 简介和分类 A Service is an application component that can perform long-running operations in the ...
- Service官方教程(7)Bound Service示例之1-同进程下直接继承Service
Extending the Binder class If your service is used only by the local application and does not need t ...
随机推荐
- 【Nginx】Nginx事件模块
一.事件处理框架概述 事件处理框架所要解决的问题是如何收集.管理.分发事件.事件以网络事件和定时器事件为主,而网络事件中以TCP网络事件为主.事件处理框架需要在不同的操作系统内核中选择一种事件驱动机制 ...
- Linux 快照
10个方法助你轻松完成Linux系统恢复 提交 我的留言 加载中 已留言 这也就是为什么系统恢复功能会让人感觉如此神奇.你可以很快地重新回到工作中去,就像什么事情都没有发生一样,也不用去管造成系统故障 ...
- input 文本框禁止输入表情
js在用户输入表情时自动过滤掉 <input type="text" id="input" maxlength="10"/> v ...
- spring 学习资料
spring 官方教程 1.3.1 http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/index.html ...
- SQL2012 尝试读取或写入受保护的内存。这通常指示其它内存已损坏
今天打开SQL2012,突然就连接不了数据库.一開始还以为是某个server崩溃了.结果试了好几个.都还是如此,弹出提演示样例如以下: 尝试读取或写入受保护的内存.这通常仅仅是其它内存已损坏.(Sys ...
- 【Android数据存储】- File
个人学习整理.如有不足之处,请不吝不吝赐教. 转载请注明:@CSU-Max 读写本应用程序数据目录中的文件 此种方法读写的文件在/data/data/<应用程序包名>中 ...
- centos 安装mysql时错误unknown variable 'defaults-file=/opt/redmine-2.6.0-2/mysql/my.cnf'
找到my.cnf所在目录.运行 chmod 664 my.cnf,再启动mysql成功
- 全局最小割模版 n^3
//点标从0-n-1, 開始时先init 复杂度n^3 //对于边(u,v,flow): //g[u][v]+=flow; //g[v][u]+=flow; typedef long long ll; ...
- iOS 浅谈MVC设计模式及Controllers之间的传值方式
1.简述你对MVC的理解? MVC是一种架构设计.它考虑了三种对象:Model(模型对象).View(试图对象).Controller(试图控制器) (1)模型:负责存储.定义.操作数据 (2)视图: ...
- css hack原理
近期看了几篇关于css hack的文章,认为不错整理一下. css hack非常多人不理解它的原理,事实上大家都知道对于不同的浏览器,CSS的解析程度不一样.因此会导致生成的页面效果不一样:特别是对于 ...