* 1.service简介
Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务。Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作。(服务和广播一样都是运行在UI线程(主活动)中的,广播如果做的事太多的话(耗时的操作),就会使得UI阻塞,没有反应)
* 2.service分类(普通服务、可交互的后台服务、前台服务)
不可交互的后台服务(普通服务)
不可交互的后台服务即是普通的Service,Service的生命周期很简单,分别为onCreate、onStartCommand、onDestroy这三个。当我们startService()的时候,首次创建Service会回调onCreate()方法,然后回调onStartCommand()方法,再次startService()的时候,就只会执行一次onStartCommand()。服务一旦开启后,我们就需要通过stopService()方法或者stopSelf()方法,就能把服务关闭,这时就会回调onDestroy()。
- 新建service 类
/**
* 不可交互的服务--普通服务
* Created by hm on 2019/3/21.
*/
public class CommonService extends Service
{
//绑定服务时调用
@Nullable
@Override
public IBinder onBind(Intent intent)
{
Log.e("Service", "onBind");
return null;
}
@Override
public void onCreate()
{
Log.e("Service", "oncreate");
super.onCreate();
}
//执行startService时调用
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.e("Service", "onStartCommand");
//这里执行耗时操作
new Thread() {
@Override
public void run() {
while (true){
try {
Log.e("Service", "doSomething");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
return super.onStartCommand(intent, flags, startId);
}
//服务被销毁时调用
@Override
public void onDestroy() {
Log.e("Service", "onDestroy");
super.onDestroy();
}
}
- AndroidManifest.xml文件中注册
<service android:name=".service.CommonService"></service>
- 启动和停止服务
btn_start.setOnClickListener(event ->startService(intent));
btn_stop.setOnClickListener(event -> stopService(intent));
-
运行结果
image.png
可交互的后台服务
“服务在后台干了许多事情,需要把这些事情反映到界面上,服务和活动之间是有交互的,比如后台播放音乐,界面上进度条、歌词等等都是需要改变的。比如地图上的位置也是会变化的。”
可交互的后台服务生命周期:onCreate()-->onBind()-->onUnbind()-->onDestory()
在普通服务的基础上使用onBind()方法时要返回一个实例,同时用另一种方式启动服务binderService(),这个方法可以将服务和活动绑定。
- 因为代码和前面大体相同,这里只列出关键变化的地方
//绑定服务时调用
@Nullable
@Override
public IBinder onBind(Intent intent)
{
Log.e("Service", "onBind");
return new MyBinder();
}
public class MyBinder extends Binder{
//服务中通过内部类的方法,定义好服务的方法
public void sendMsg(){
Log.e("Service", "sendMsg");
}
}
btn_start.setOnClickListener(event -> bindService(intent, mCon, BIND_AUTO_CREATE));
btn_stop.setOnClickListener(event -> unbindService(mCon));
- binderService(bindIntent,connection,BIND_AUTO_CREATE)这个方法有三个参数,第一个是intent,用来指定服务;第二个参数是connection用来表示活动和服务的连接,这个类中可以使用服务返回的binder实例。第三个参数是服务的标志。
最关键的一步:创建conneection,ServiceConnection类中有两个方法onServiceConnected、onServiceDisconnected,这两个方法分别在服务与活动绑定和解除绑定的时候调用。
ServiceConnection mCon = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
//拿到后台服务代理对象
CommonService.MyBinder myBinder= (CommonService.MyBinder) service;
//调用后台服务方法
myBinder.sendMsg();
}
@Override
public void onServiceDisconnected(ComponentName name)
{
}
};
- 这里和startService的区别在于多了一个ServiceConnection对象,该对象是用户绑定后台服务后,可获取后台服务代理对象的回调,我们可以通过该回调,拿到后台服务的代理对象,并调用后台服务定义的方法,也就实现了后台服务和前台的交互。
前台服务
由于后台服务优先级相对比较低,当系统出现内存不足的情况下,它就有可能会被回收掉,所以前台服务就是来弥补这个缺点的,它可以一直保持运行状态而不被系统回收。例如:天气app在状态栏中的天气预报,音乐app放在前台状态栏的播放控制器,词典app放在前台的快捷方式等等。
- 前台服务创建很简单,其实就在Service的基础上创建一个Notification,然后使用Service的startForeground()方法即可启动为前台服务。上代码,具体实现
public class ForegroundService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
showNotification();
}
//启动前台通知
private void showNotification() {
//创建通知详细信息
Notification.Builder mBuilder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("xxxxx")
.setContentText("xxxxxxx");
//创建点击跳转Intent
Intent intent = new Intent(this, MainActivity.class);
//创建任务栈Builder
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
//设置跳转Intent到通知中
mBuilder.setContentIntent(pendingIntent);
//获取通知服务
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//构建通知
Notification notification = mBuilder.build();
//显示通知
nm.notify(0, notification);
//启动为前台服务
startForeground(0, notification);
}
IntentService
IntentService是专门用来解决Service中不能执行耗时操作这一问题的,创建一个IntentService也很简单,只要继承IntentService并覆写onHandlerIntent函数,在该函数中就可以执行耗时操作了。
IntentService既可以开启支线程处理耗时任务,又可以自动停止服务,不用在调用服务的onDestroy()方法,集开启支线程和自动停止于一体,
public class MyIntentService extends IntentService {
public MyIntentService (String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
//在这里执行耗时操作
}
网友评论