服务:Android系统的后台服务组件,在后台长时间运行并且不提供用户界面的应用程序组件
服务的特点:
- 1.没有用户界面
- 2.不会轻易被Android系统终止
- 3.在系统资源恢复后Service也将自动恢复运行状态
- 4.可用于进程间通信
一、启动式服务
销毁服务时函数的调用:onDestroy()
多次销毁服务,不会多次调用onDestroy(),但也不会报错.
启动式服务的特点:
- A:一旦调用者启动了服务,则调用者和服务就没有直接关系了,即调用者退出了,服务照样在后台继续运行.
- B:启动式服务无法将服务的执行结果返回给调用者,如Activity.
- C:启动式服务无法调用服务中的公有方法
- D:服务生命周期函数都运行在主线程中
1、启动服务
Intent service=new Intent(this,ServiceLifeCycler.class);
service.putExtra(“startMusic”,“启动音乐”);
service.putExtra(“pauseMusic”,“暂停音乐”);
service.putExtra(“resetMusic”,“重置音乐”);
service.putExtra(“stopMusic”,“停止音乐”);
//启动服务
this.startService(service);
2、停止服务(它杀)
this.stopService(service);
自定义服务的编写步骤:
1.编写一个子类继承Service或者它的子类并重写抽象方法onBind(Intent intent)
public class ServiceLifeCycler extends Service {
public IBinder onBind(Intent intent) {
return null;
}
}
2.由于服务是android四大组件(Activity,Content Provider,BroadcastReceiver,Service)之一,必须在功能清单文件中进行注册:
<service android:name=".service.ServiceLifeCycler"/>
服务的存在形式有两种:
- A:启动式服务:一旦调用者启动了服务,那么即使调用者销毁了,对启动的服务没有影响.
- B:绑定式服务:一旦调用者绑定了服务,那么在调用者销毁时服务也会一块销毁.
启动式服务的生命周期函数有:
onCreate()====>onStartCommand()===>onStart()=====>onDestroy()
第一次启动服务时自动调用的生命函数有:
onCreate()===>onStartCommand()====>onStart();
第二次启动服务时自动调用的生命周期函数有
:onStartCommand()===>onStart();
结论:
- onCreate()只有在第一次创建服务时才会自动调用的方法;
- onStartCommand():每次启动服务都会自动调用的方法
- onStart():每次启动服务都会自动调用的方法
onDestroy():当服务被销毁时自动调用的方法,主要做资源释放工作等
用户停止服务时自动调用的方法为:onDestroy();多次停止服务不会多次执行onDestory()方法,但也不会报错.
服务的生命周期函数都运行在主线程中,因此如果想做耗时操作,则必须开启子线程来做;
调用者比如Activity如果采用startService(intent)启动了服务,则调用者比如activity无法调用服务中的公有方法,因为activity得不到服务对象.
二、IntentServce
IntentServce的特点:
- 1.创建一个工作器线程用来执行所有的意图对象,意图对象传递给onStartCommand()方法.
- 2.创建一个工作队列,每次只能通过一个意图对象,意图对象是通过onStartCommand()方法传递给工作队列的,把意图对象从工作
队列中取出来以后会自动传递给onHandleIntent(Intent intent)的形参intent,做耗时操作,当前所有的意图对象都通过
工作队列传递给onHandleIntent(Intent intent)的形参intent后,服务会自杀. - 3.提供了onBind()方法的默认实现,返回null;
IntentService的使用:
- 1.编写一个类继承IntentService并提供无参构造函数,在无参构造函数中必须调用父类的带一个字符串参数的构造函数,这个字符串就是子线程的名称.
- 2.必须重写父类的抽象方法onHandlerIntent(Intent intent)做耗时操作,当所有的意图对象都传递过来执行完毕后服务会自杀.
public class MyIntentService extends IntentService {
public MyIntentService() {
//参数childThread是子线程的名称
super("childThread");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
/**
* 当从工作队列中取出意图对象后会传递给当前方法的形参intent,并做耗时操作,当前取出工作队列中所有的意图对象并处理完毕后会自杀.
* @param intent 启动服务是使用的意图对象
*/
@Override
protected void onHandleIntent(Intent intent) {
String name=intent.getStringExtra("name");
String threadName=Thread.currentThread().getName();
//模拟耗时操作
SystemClock.sleep(3000);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
三、绑定服务
绑定式服务的编写和使用过程:
- A:编写一个类继承Service或者它的子类
- B:重写相关生命周期方法
onCreate()===>onBind()===>onUnbind()===>onRebind()===>onDestroy()
- C:在功能清单文件中进行注册
<service android:name=".service.ServiceWithBindLifeCycler"></service>
- D:在Activity中可以绑定服务和解绑服务
Intent service=new Intent(this,ServiceWithBindLifeCycler.class);
//绑定服务
this.bindService(
service, //意图对象并且指定了启动源和启动目标
connection,//服务连接对象
this.BIND_AUTO_CREATE//绑定选项,当前选项表示服务绑定即创建
);
//解绑服务
this.unbindService(connection);
绑定式服务的特点:
- A:当用户第一次绑定服务时会自动调用onCreate()===>onBind()方法,多次绑定服务不会多次调用onCreate()和onBind()方法
- B:如果解绑服务,则会自动调用
onUnbind()===>onDestroy();
- C:多次解绑服务会报如下异常:
java.lang.IllegalStateException: Could not execute method of the activity。。。。
Caused by: java.lang.IllegalArgumentException:
Service not registered: com.example.servicewithbindcyclerdemo03.MainActivity$1@5351c19c
public class MainActivity extends AppCompatActivity {
/**
* 声明服务对象
*/
private BoundServiceLifeCycler boundServiceLifeCycler;
/**
* 是否成功绑定服务的标志
*/
private boolean isBindSuccess;
/**
* 声明并实例化服务连接对象
*/
private ServiceConnection conn=new ServiceConnection() {
/**
* 当客户端成功绑定服务后自动调用的方法,如果绑定成功,则将绑定方法的返回值传递给形参service对象
* @param name
* @param service
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//把父类的对象service强制转换成子类MyBinder类型的对象
BoundServiceLifeCycler.MyBinder myBinder= (BoundServiceLifeCycler.MyBinder) service;
boundServiceLifeCycler=myBinder.getService();
//在调用者Activity中成功的调用了服务对象中的共有方法
int randomNumber=boundServiceLifeCycler.getRandom();
//绑定服务成功将标志位置为true
isBindSuccess=true;
}
/**
* 当服务意外断开连接时自动调用的方法
* @param name
*/
@Override
public void onServiceDisconnected(ComponentName name) {
isBindSuccess=false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 绑定服务
* @param view
*/
public void boundService(View view){
Intent intent=new Intent(this, BoundServiceLifeCycler.class);
//绑定服务需要三个参数:1.意图对象 2.服务连接对象,3.指定一个标志,绑定即自动创建服务
this.bindService(
intent,//意图对象
conn, //服务连接对象
Context.BIND_AUTO_CREATE//标志,绑定服务时如果服务还没有创建则自动创建服务
);
}
/**
* 解绑服务,
* 多次解绑服务会报如下错误错:
* java.lang.IllegalArgumentException:
* Service not registered: com.hsj.example.boundservicedemo03.MainActivity$1@53530268
*
* @param view
*/
public void unboundService(View view){
if(this.isBindSuccess){
//解绑服务,只需要传递一个参数:conn对象
this.unbindService(conn);
//成功解绑后还原标志位
this.isBindSuccess=false;
}else {
Toast.makeText(this, "必须先绑定服务才能解绑!", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(this.isBindSuccess){
//解绑服务,只需要传递一个参数:conn对象
this.unbindService(conn);
//成功解绑后还原标志位
this.isBindSuccess=false;
}
}
}
public class BoundServiceLifeCycler extends Service {
/**
* 当服务第一次被创建时自动调用的方法
*/
@Override
public void onCreate() {
}
/**
* 声明随机数对象
*/
private Random random=new Random();
/**
* 返回0到10之间的随机数,包括0,不包括10,[0,10)
* @return
*/
public int getRandom(){
int randomNumber= random.nextInt(10);
return randomNumber;
}
/**
* 当绑定服务时自动调用的方法,如果绑定成功则会将当前方法的返回值对象传递给
* ServiceConnection类中的方法onServiceConnected(ComponentName name, IBinder service)
* 的形参service
*
* @param intent
* @return 如果返回值为null表示绑定失败,非null表示绑定成功
*/
@Override
public IBinder onBind(Intent intent) {
MyBinder myBinder=new MyBinder();
return myBinder;
}
/**
* 自定义Binder的子类MyBinder类
*/
public class MyBinder extends Binder{
/**
* 在内部类中访问外部类对象
* @return 外部类对象
*/
public BoundServiceLifeCycler getService(){
return BoundServiceLifeCycler.this;
}
}
/**
* 当解绑服务时自动调用的方法
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
/**
* 当之前绑定过服务,并且onUnbind(Intent intent)方法的返回值为true,再次绑定时自动调用的方法
* @param intent
*/
@Override
public void onRebind(Intent intent) {
}
/**
* 当服务销毁时自动调用的方法
*/
@Override
public void onDestroy() {
}
}
四、启动式服务和绑定式服务的混合使用
-
1.第一次启动服务时生命周期函数的调用顺序为:onCreate()>onStartCommand()>onStart();
-
2.接着绑定服务时生命周期函数的执行顺序为:onBind()====>onServiceConnected()(不是服务的生命周期函数);
-
3.继续解绑服务时生命周期函数的调用顺序为:onUnbind(Intent intent);
-
4.最后停止服务时函数的调用顺序为:onDestroy();
1,2,3,2,3,4对应生命周期函数的调用顺序为:
onCreate()===>onStartCommand()===>onStart()=====>
onBind()===>onServiceConnected()=====>onUnbind()=====>onServiceConnected()====>onRebind()(如果想调用onRebind()方法必须在之前解绑服务时调用onUnbind()方法时返回值为true,否则不会调用onRebind()方法)====>onUnbind()=====>onDestroy().
1,2,4,3对应的生命周期函数的调用顺序为:
onCreate()===>onStartCommand()===>onStart()====>
onBind()====>onServiceConnected()====>
停止服务不会调用onDestroy()方法,因为服务还有一条绑定服务的关系引用地址onUnbind()====>onDestroy()
2,1,3,4对应的生命周期函数的调用顺序为:
onCreate()===>onBind()===>onServiceConnected()====>
onStartCommand()===>onStart()=====>
onUnbind()===>onDestroy().
2,1,4,3对应的生命周期函数的调用顺序为:
onCreate()===>onBind()===>onServiceConnected()====>
onStartCommand()===>onStart()=====>
停止服务不会调用onDestroy()方法,因为服务还有一条绑定服务的关系引用地址onUnbind()====>onDestroy().
结论:不管是启动式和还是绑定式服务,都会首先自动调用onCreate(),如果先启动服务,则会在调用onCreate()方法之后自动调用onStartCommand()==>onStart(),
如果先绑定服务,则会在调用完onCreate()方法之后自动调用onBind()方法,多次启动服务,
不会多次调用onCreate()方法,但会多次调用onStartCommand()和onStart()方法,多次绑定服务,
不会多次调用onCreate()和onBind()方法,多次停止服务不会多次调用onDestroy()方法,多次解绑服务会报错.
小技巧:
如果想绑定服务后,解绑服务不要让服务销毁,方便下次继续绑定同一个服务,可以先启动服务,之后在绑定服务,
在解绑服务时不会销毁服务,下次可以继续重新绑定上次启动好的服务.