转载请标明出处:http://blog.csdn.net/wu_wxc/article/details/51377512
本文出自【吴孝城的CSDN博客】
关于Service的生命周期,可以看:Services的生命周期
IntentService
如果程序不需要同时处理多个请求,IntentService将是最好的选择。
可以启动IntentService多次,每一次耗时操作都会以队列的形式在IntentService的onHandleIntent回调方法中执行,每次只执行一个工作线程,执行完再执行下一个。这种单线程形式保证了主线程(UI线程)不会被阻塞
处理完所有的启动请求后,IntentService会自动停止服务,所以不需要调用stopSelf()来停止服务。
提供缺省的onBind()实现代码,因为不提供绑定,所以它返回null。
提供缺省的onStartCommand()实现代码,它把intent送入工作队列,稍后会再传给你的onHandleIntent()实现代码。
以上所有的步骤汇成一个结果,我们需要做的就是实现onHandleIntent()来完成客户端提交的任务,还有就是为服务提供一小段构造方法
以下是一个IntentService的实现例子:
public class MyIntentService extends IntentService {
//必须实现一个构造方法,且以工作线程名称作为参数
public MyIntentService() {
super("MyIntentService");
}
/**
* 从缺省的工作空间调用本方法,并用启动服务的Intent作为参数
* 本方法返回后,IntentService会适时终止这个服务
*/
@Override
protected void onHandleIntent(Intent intent) {
// 我们可以在这里执行一些工作,如下载文件等
}
}
如果想重写其他回调方法,要确保调用一下父类的实现代码以便IntentService能正确处理工作线程的生命周期。
下面程序回调了Service生命周期的其他方法
MainActivity.java
package cn.wuxiaocheng.intentservice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onHandleIntent(View v) {
startService(new Intent(MainActivity.this, MyIntentService.class));
}
}
MyIntentService.java
package cn.wuxiaocheng.intentservice;
import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
public class MyIntentService extends IntentService {
//必须实现一个构造方法,且以工作线程名称作为参数
public MyIntentService() {
super("MyIntentService");
}
/**
* 从缺省的工作空间调用本方法,并用启动服务的Intent作为参数
* 本方法返回后,IntentService会适时终止这个服务
*/
@Override
protected void onHandleIntent(Intent intent) {
//我们可以在这里执行一些工作,如下载文件等
try {
//作为演示,这里我让它休息3秒,然后输出onHandleIntent
Thread.sleep(3000);
System.out.println("onHandleIntent");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
System.out.println("setIntentRedelivery");
}
@Override
public IBinder onBind(Intent intent) {
//不支持绑定,所以返回null
return null;
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="cn.wuxiaocheng.intentservice.MainActivity">
<Button
android:onClick="onHandleIntent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="onHandleIntent" />
</RelativeLayout>
还有要在配置清单文件里添加声明 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.wuxiaocheng.intentservice">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyIntentService"
android:exported="false"></service>
</application>
</manifest>
其中第19-21行就是
Service
下面说下继承Service的使用
如果Service需要多线程运行,可以继承Service来完成每个Intent处理。
对于每一个启动请求,它都以一个工作线程来完成处理,并且每次只处理一个请求。因为是自行处理每个onStartCommand()调用,所以可以为每个请求创建一个新的线程,并立即运行它们,不需要等待前一个请求处理完毕。这就实现了多线程的操作。
来个小例子
MainActivity.java
package cn.wuxiaocheng.started;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(MainActivity.this, MyService.class);
}
public void startService(View v) {
startService(intent);
}
}
MyService.java
package cn.wuxiaocheng.started;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
public class MyService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
//程序从线程接收消息
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// 通常我们在这里执行一些操作,如下载文件
// 这里我们让它休息3秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
//恢复中断状态
Thread.currentThread().interrupt();
}
//通过startId来停止服务,这样我们就不用在处理其他工作的过程中再来停止服务
stopSelf(msg.arg1);
}
}
@Override
public void onCreate() {
// 启动运行服务的线程
// 注意要创建一个单独的线程,因为服务通常运行于进行的主线程中,我们不想阻塞主线程
// 还要赋予它后台服务的保优先级,这样处理密集的工作就不会干扰我们的UI
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// 获得HandlerThread的Looper的队列并用于Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
System.out.println("onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("service starting");
// 对于每一个请求,都发送一个消息来启动处理。
// 同时传入启动ID,以便任务完成后我们知道该终止哪一个请求
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// 如果我们被杀死,那从这里返回后被重启
return START_STICKY;
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
}
@Override
public IBinder onBind(Intent intent) {
// 不提供绑定,所有返回null
return null;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="cn.wuxiaocheng.started.MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="startService"
android:text="startService" />
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.wuxiaocheng.started">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
onStartCommand()的返回值必须是以下常量之一 START_NOT_STICKY 在onStartCommand()返回后,如果系统kill这个服务,系统不会自动重启这个服务,直到startService(Intent intent)方法再次被调用。 START_STICKY 如果系统在onStartCommand()后杀死了这个服务,则将重启并调用onStartCommand(),但不会再次传入一个intent,而是用null的intent来调用onStartCommand(),如果还有启动服务的intent未发送完,那么这些剩下的intent会继续发送。这适用于媒体播放器(或类似服务),它们不执行命令,但需要一直运行并随时待命。 START_REDELIVER_INTENT 如果系统在onStartCommand()返回后杀死了服务,则将重建服务并用上一个已送过的intent调用onStartCommand()。任何未发送完的intent也都会依次送入。这适用于那些需要立即恢复工作的活跃服务,比如下载文件。
Started:非绑定服务
package cn.wuxiaocheng.started;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class MyService extends Service {
public MyService() {
}
@Override
public void onCreate() {
//线程开始被创建
System.out.println("onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//启动线程后执行的内容
System.out.println("onStartCommand");
// 服务被杀死看后的表现
return START_STICKY ;
}
@Override
public void onDestroy() {
//线程摧毁
System.out.println("onDestroy");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
//不允许绑定,所有返回null
return null;
}
}
Bound:绑定服务
MyService.java
package cn.wuxiaocheng.bound;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service {
IBinder mBinder; // 客户端绑定接口
boolean mAllowRebind; // 声明是否使用onRebind
public MyService() {
}
@Override
public void onCreate() {
//服务被创建
System.out.println("onCreate");
}
@Override
public IBinder onBind(Intent intent) {
// 客户端调用bindService()绑定服务
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
//所有扩客户端都通过unbindService()解除绑定
return mAllowRebind;
}
@Override
public void onDestroy() {
//服务被摧毁
System.out.println("onDestroy");
}
}
android:exported
该属性决定该服务是否能够被其他应用程序组件调用或跟它交互。值为true时,能够被调用或交互,值为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。
android:enabled
该属性决定系统是否能实例化这个服务,值为true时,则能够被实例化,值为false时,不能被实例化,默认值为true