为什么要使用Service
我们在做项目过程中,经常遇到一些任务需要再后台执行(比如后台播放音乐、上传、下载等),这个时候就是Service大展身手的时候了。
举个例子:
音乐播放器在播放音乐的过程中,我们按下Home键,前往其他APP执行别的操作,假如播放音乐的操作全都在Activity中完成,那么我们退到后台时,这个Activity很有可能被清掉,就不能正常播放音乐了。但是,如果你用了Service,情况就不一样了,Service的生命周期是和Activity不一样的,系统清理的优先级也不一样,所以即使退到后台,照样能正常播放音乐。
这时候,有朋友又说了:Thread!我可以用一个Thread来播放音乐啊,你这个服务是不是就是相当于开启了一个Thread?
那我就来扒一扒Thread和Service的区别。
- Thread:Thread是程序执行的最小单元,它是分配CPU的基本单位。
- Service:Service是Android中的一种机制,它是在Main线程中运行的。总而言之,Service和Thread半毛钱关系都没有。
直观而言,Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。当你重新进入这个Activity时,也不要妄想你能通过这个Activity去操控之前的那个Thread。
怎么解决这个问题呢?
这个时候你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。
Service是什么
service就是android系统中的服务,它有这么几个特点:它无法与用户直接进行交互、它必须由用户或者其他程序显式的启动、它的优先级比较高,它比处于前台的应用优先级低,但是比后台的其他应用优先级高,这就决定了当系统因为缺少内存而销毁某些没被利用的资源时,它被销毁的概率很小哦。
Service怎么用
Service的启动方式分为startService和bindService两种。
startService
0、 新建类继承Service
public class MusicService extends Service
重写onCreate方法
Service在创建时调用的方法,可以用来做数据初始化,Service在没有停止之前,只会执行一次。实现onBind方法
由于Service是一个抽象类,定义了一个onBind抽象方法,所以必须实现此抽象方法,return null 即可,此方法在startService方式用不上,无需理会。重写onStartCommand方法
Service创建后会调用onStartCommand,此方法中可以接收调用者传递过来的参数,并且可以编写需要的逻辑代码,当重复调用Service时,onStartCommand会重复执行,onStart方法已弃用。重写onDestroy方法
Service在退出时调用,此方法中可以编写释放资源的操作。在AndroidManifest文件中注册Service
<service android:name="com.lenovo.mymediaplayer.service.MusicService" >
</service>
- 使用startService方法启动Service
Intent serviceIntent = new Intent(MusicActivity.this, MusicService.class);
// 绑定服务,启动
startService(serviceIntent);
- 使用stopService方法停止Service
使用startService启动Service的总结
- onCreate只会执行一次,只要调用startService,onStartCommand一定会执行
- Service运行在main线程中,做耗时操作需另开子线程。
- 通过Intent进行传参,在onStartCommand中接收参数。
- 无法获得Service对象,不能直接操作Service中的属性和方法。
- 调用stopService后,Service会执行onDestroy方法后停止。
bindService
- step1:新建类继承Service
- step2:实现onBind方法
这里不同于startService中实现onBind方法那样简单。这里需要在此方法中返回一个Binder子类对象。 - step3:重写onCreate方法
- step4:重写onUnBind方法
在调用unbindService方法解除绑定后,触发此回调函数 - step5:重写onDestroy方法
- step6:在AndroidManifest中注册Service
- step7:实现ServiceConnection接口
这里是难点,通过代码示范。 - step8:通过bindService绑定Service
- step9:通过unbindService解绑Service
代码示范
Service代码
public class MyService extends Service{
private int count;
private MyBinder binder = new MyBinder();
private boolean stopFlag;
public class MyBinder extends Binder{
public int getCount(){
return count;
}
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("执行onBind方法...");
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("执行onUnBind方法...");
return true;
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("执行onCreate方法");
// new Thread(new MyThread()).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("执行onStartCommand方法");
//三种返回值(仅限使用startService方法启动时有效果)
//START_STICKY,服务被异常杀掉后,会重启服务
//START_NOT_STICKY,服务被异常杀掉后,不会重启服务
//START_REDELIVER_INTENT,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
System.out.println("rebind");
}
@Override
public void onDestroy() {
super.onDestroy();
stopFlag = true;
System.out.println("执行onDestroy方法");
}
class MyThread extends Thread{
@Override
public void run() {
while(!stopFlag){
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"---"+Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
System.out.println(count);
}
}
}
}
启动Service的Activity代码
public class HomeActivity extends Activity {
private Button btn1;
private Button btn2;
private Intent intent;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("onDisConnected");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("connected");
MyServiceTwo ms = ((MyServiceTwo.MyBinder) service).getService();
ms.printServiceName();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 从5.0开始,谷歌要求必须使用显示intent启动service
intent = new Intent(this, MyService.class);
btn1 = (Button) findViewById(R.id.btn1);
btn2 = (Button) findViewById(R.id.btn2);
btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}
});
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
unbindService(conn);
}
});
}
}
使用bindService方式绑定Service的总结:
- onCreate,onBind只会执行一次
- Service运行在main线程中,做耗时操作需另开子线程。
- 可以直接操作Service中的属性和方法。
- 调用unbindService后,Service会执行onUnbind,onDestroy方法后停止。