Service的生命周期与启动/停止服务
timg.jpgpublic class MyService extends Service {
private final static String TAG = "MyService";
public MyService() {
}
//服务被创建时调用
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
//服务被启动时调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//服务被销毁时调用
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_service:
Intent startIntent = new Intent(this, MyService.class);
//启动服务
startService(startIntent);
break;
case R.id.stop_service:
Intent stopIntent = new Intent(this, MyService.class);
//停止服务
stopService(stopIntent);
break;
default:
break;
}
}
启动服务后的日志为
图片.png当再次点击启动服务按钮时,日志为
图片.png可以看出onCreate()方法不再执行,即onCreate()方法只会在服务第一次被创建的时候执行。
点击停止服务的按钮时,日志为
即onDestory()方法被执行
在Service中调用stopSelf()方法也可以停止服务
Activity与Service通信
Service代码
//Activity与Service通信时使用
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return mBinder;
}
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload() {
Log.d(TAG, "startDownload");
}
public int getProcess() {
Log.d(TAG, "getProcess");
return 0;
}
}
Activity代码
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
//Activity与Service绑定成功时调用
public void onServiceConnected(ComponentName componentName, IBinder service) {
//向下转型得到DownloadBinder实例,该实例可以调用DownloadBinder的public方法
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProcess();
}
//Activity与Service解除绑定时调用
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
/**
* 绑定服务,第一个参数为Intent对象,
* 第二个参数为ServiceConnection对象
* 第三个参数为flag标识,BIND_AUTO_CREATE表示自动创建service,
* 此时onCreate()方法执行,onStartCommand()方法不会执行
*/
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
//解除绑定
unbindService(connection);
default:
break;
日志打印结果为
图片.png即绑定服务时onBind()方法会被调用,且通过其返回一个Binder对象给Activity,从而在Activity中通过对象转型来调用Service中的方法
点击解除绑定按钮日志输出为
图片.png当执行startService()后执行bindService()方法,此时要销毁服务需要同时调用stopService()方法和unbindService()方法后,onDestory()方法才会被调用
启动服务
图片.png绑定服务
图片.png停止服务和解除绑定服务
图片.pngService的扩展知识
使用前台服务
前台服务的特征:有一个运行图标一直在系统的状态栏显示
//服务被创建时调用
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
Intent intent=new Intent(this,MainActivity.class);
/**
* 第一个参数为上下文对象
* 第二个参数为requestCode返回码
* 第三个参数为Intent对象
* 第四个参数为flags标识
*/
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,0);
Notification notification=new NotificationCompat.Builder(this)
.setContentTitle("This is content title")
.setContentText("This is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setContentIntent(pendingIntent)
.build();
//启动前台服务,第一个参数为通知的id
startForeground(1,notification);
}
GIF.gif
服务的特征
服务是运行在主线程中的,耗时操作会造成ANR
在Service与Activity中分别加入以下代码打印线程id
Log.d("MyService", "MainActivity thread id is " + Thread.currentThread().getId());
Log.d("MyService", "Service thread id is " + Thread.currentThread().getId());
图片.png
由Log打印日志可知Service与Activity确实运行在同一线程中,因此不能在Service中进行耗时操作,正确的使用方法是在每个服务中去开启一个子线程,在子线程中进行耗时操作,写法可以为
//服务被启动时调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
new Thread(new Runnable() {
@Override
public void run() {
//在子线程中处理耗时操作
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
开发中可能出现忘记开启线程或调用stopSelf()方法结束服务,所以可以使用IntentService类来创建一个异步且会自动停止的服务。
IntentService类
public class MyIntentService extends IntentService {
//该无参构造方法必须实现,且格式固定,需要调用父类的有参构造函数来实例化Service
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//根据intent的不同来处理不同的逻辑
Log.d("MyIntentService", "Thread id is " + Thread.currentThread().getId());
String value = intent.getStringExtra("test");
Log.d("MyIntentService", "intentService2 " + value);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy");
}
}
MainActivity
case R.id.start_intent_service:
//启动IntentService服务
Log.d("MyIntentService", "Activity thread id is " + Thread.currentThread().getId());
Intent intentService = new Intent(this, MyIntentService.class);
Intent intentService2 = new Intent(this, MyIntentService.class);
intentService2.putExtra("test", "executed");
startService(intentService);
startService(intentService2);
break;
图片.png
由日志可以看出IntentService与Activity没有运行在同一线程中,且onHandleIntent()方法会先后处理不同的intent,只有处理完所有的intent请求后onDestory()方法才会执行,以此自动停止服务。
网友评论