引言: 四大组件都是运行在主线程 , Android中的服务也是在后台运行 ,服务可以理解成是在后台运行并且是没有界面的Activity。
①当一个程序第一次启动的时候,Android会启动一个LINUX进程和一个主线程。默认的情况下,所有该程序的组件都将在该进程和线程中运行。 同时Android
会为每个应用程序分配一个单独的LINUX用户。Android会尽量保留一个正在运行进程,只在内存资源出现不足时,Android会尝试停止一些进程从而释放足够
的资源给其他新的进程使用, 也能保证用户正在访问的当前进程有足够的资源去及时地响应用户的事件。那么该停止那个进程呢?于是引入进程优先级。
②进程优先级
(1)Foreground process 前台进程 用户正在交互 可以理解成相 当于 Activity执行onResume方法。
如果有以下的情形的那么也属于前台进程:
这个进程运行着一个正在和用户交互的Activity(这个Activity的onResume()方法被调用)。
这个进程里有绑定到当前正在和用户交互的确Activity的一个service。
这个进程里有一个service对象,这个service对象正在执行一个它的生命周期的回调函数(onCreate(), onStart(), onDestroy())
这个进程里有一个正在的onReceive()方法的BroadCastReiver对象。
(2)Visible process 可视进程 用户没有在交互 但用户还一直能看得见页面 相当于Activity执行了onPause方法
如果有如下的一种情形就是可见进程:
这个进程中含有一个不位于前台的Activity,但是仍然对用户是可见的(这个Activity的onPause()方法被调用),这是很可能发生的,例如,如果前台A
civity是一个对话框的话,就会允许在它后面看到前一个Activity。
这个进程里有一个绑定到一个可见的Activity的Service。
(3)Service Process 服务进程 通过startService()开启了一个服务
(4)Background process 后台进程 当前用户看不见页面 相当于Activity执行了onStop方法
5)Empty process 空进程,未运行任何程序组件。运行这些进程的唯一原因是作为一个缓存,缩短下次程序需要重新使用的启动时间。系统经常中止这些进
程,这样可以调节程序缓存和系统缓存的平衡。
Service通常总是称之为“后台服务”,其中“后台”一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面,因此,从实际业务需求上
来理解,Service的适用场景应该具备以下条件:
1.并不依赖于用户可视的UI界面(当然,这一条其实也不是绝对的,如前台Service就是与Notification界面结合使用的);
2.具有较长时间的运行特性。
同样,服务也具有生命周期,由于是四大组件,创建时,也需要在清单文件中进行配置。
定义服务,需要在清单文件进行配置。
(1)服务通过startservice方式开启,第一次点击按钮开启服务,会执行服务的onCreate 和 onStart方法。
(2)如果第二次开始在点击按钮开启服务,服务之后执行onStrat方法。
(3)服务被开启后,会在设置页面里面的running界面找得到这个服务。
(4)startservice 方式开启服务 服务就会在后台长期运行 直到用户手工停止 或者调用StopService方法 服务才会被销毁。
示例:
// 点击按钮开启服务
public void click1(View v) {
Intent service = new Intent(this, FirestService.class);
// 开启服务
startService(service);
}
// 点击按钮关闭服务
public void click2(View v) {
Intent service = new Intent(this, FirestService.class);
stopService(service);
}
(1)当点击按钮第一次开启服务,会执行服务的onCreate方法 和 onBind()方法。
(2) 当我第二次点击按钮在调用bindservice,服务没有响应。
(3) 当activity销毁的时候服务也销毁,不求同时生但求同时死。
(4)通过bind方式开启服务,服务不能再设置页面里面找到,相当于是一个隐形的服务。
(5)bindservice不能多次解绑,多次解绑会报错。
原因是:为了调用服务里的方法。。
(1)定义一个服务,服务里面有一个方法需要Activity调用。
public void method() {
System.out.println("我是服务的方法");
}
(2)在服务中,定义一个(中间人)内部类MyBinder 继承Binder; binder可以理解成一个中间人为我们提供调用服务中方法。
public class MyBinder extends Binder{
//定义一个方法调用服务中的方法
public void callMethod(){
method();
}
}
(3)在服务中,重写onbind方法里面把我们定义的(中间人)对象mybind返回 。 (当外部用bindservice方式开启服务时,会调用该方法。)
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
(4)在Activity的oncreate 方法里面调用bindservice 目的是为来获取我们定义的(中间人)对象。
// 绑定服务 (连接服务)
Intent service = new Intent(this, TestService.class);
MyConn conn = new MyConn();//用于监视服务的状态
bindService(service, conn, BIND_AUTO_CREATE);
(5)在activity中获取(中间人)对象,即定义一个继承ServiceConnection的内部类
// 监视服务的状态
private class MyConn implements ServiceConnection {
// 连接成功后调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取中间人对象
myBinder = (MyBinder) service;
}
//失去连接的时候调用
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
(6)拿到中间人对象后就可以间接的调用到服务里面的方法
//点击按钮,调用TestService 服务里面的方法
public void click(View v) {
//通过我们定义的中间人对象调用服务里面的方法
myBinder.callMethod();
}
此外,引入通过接口方式调用服务里面的方法。
接口可以隐藏代码内部的细节,让程序员暴露自己只想暴露的方法。
(7)定义一个接口 把想暴露的方法都定义在接口里面
(8)我们定义的中间人对象 实现我们定义的接口
(9)在获取我们定义的中间人对象方式变了
public interface Iservice {
//把服务想暴露的方法定义在接口里
public void callMethod();
}
同时,中间人实现这个借口。
private class MyBinder extends Binder implements Iservice
需求:我既想让服务在后台长期运行,又想调用服务里面的方法 。
因此就用到混合方式开启服务 。
(1)先调用startService()方法,保证服务在后台长期运行。
(2)调用bindservice(),目的获取我们定义的中间人对象 调用服务里面的方法。
(1)远程服务 运行在其他应用里面的服务 。
(2)本地服务 运行在自己应用里面的服务 。
(3)进行进程间通信。IPC。
(4)aidl:Android interface Defination Language Android接口定义语言,专门是用来解决进程间通信的
(5)应用场景相对较少。
1.服务可以理解成是在后台运行并且是没有界面的Activity。
2.开启服务的两大方式的特点:start方式,具有在后台长期运行的特点;bind方式,具有可以调用服务内部的方法,同时会随activity的销毁而
销毁。因此,可以结合两者的特点进行混合开启服务来达到更好的效果,即:既想服务长期运行,又想暴露服务中的方法。
3.接口:可以隐藏代码内部的细节,让程序员暴露自己只想暴露的方法。
4.Binder可以理解成一个中间者,来提供调用服务中的方法。
5.牢记什么情况下进程处于什么优先级。