1.服务和进程优先级
什么是服务?
- windows下的服务:没有界面、长期运行在后台的应用程序;
- android下的服务:应用程序的一个组件,没有界面activity,长期运行在后台;
- 进程
- 进程是应用程序运行的载体。
- 进程与应用程序之间的关系: linux操作系统创建一个进程,这个进程负责运行dalvik虚拟机,Android的应用程序都是运行在dalvik虚拟机上的。
进程的生命周期:
- 应用程序一启动的时候就创建了进程;
- 当应用程序退出的时候进程并没有退出;
- 只有手工停止这个进程,进程才会结束;
操作系统尽量长时间的运行应用程序的进程,为了保证内从空间不被大量占用,它会按照进程的优先级,从低到高一级一级的杀死进程,直到内存空间被清理的差不多。
进程的等级:
Foreground process(前台进程)
应用程序,用户当前操作所必须的进程。满足以下任一条件时,进程被视作处于前台进程:
其中运行着正与用户交互的Activity(Activity对象的 onResume() 方法已被调用)。
其中运行着被正与用户交互的activity绑定的服务Service。
其中运行着“前台”服务Service——服务以startForeground()方式被调用。
其中运行着正在执行生命周期回调方法(onCreate()、onStart()或onDestroy())的服务Service。
其中运行着正在执行onReceive()方法的BroadcastReceiver。
Visible process (可视进程)
应用程序的ui界面,用户还可以看到,但是不能操作了。满足以下任一条件时,进程被认为是可见的:
其中运行着不在前台的Activity,但用户仍然可见到此activity(onPause()方法被调用了)。
其中运行着被可见(或前台)activity绑定的服务Service。
可见进程被认为是非常重要的进程,除非无法维持所有前台进程同时运行了,它们是不会被终止的
Service process (服务进程)
应用程序没有界面,但是有一个后台的服务还处于运行状态。此进程运行着由startService()方法启动的服务,它不会升级为上述两级别。
尽管服务进程不直接和用户所见内容关联,但他们通常在执行一些用户关心的操作(比如在后台播放音乐或从网络下载数据)。
除非内存不足以维持所有前台、可见进程同时运行,系统会保持服务进程的运行。
Background process(后台进程)
应用程序没有服务处于运行状态,应用程序被最小化了,activity执行了onstop方法。
包含目前用户不可见activity(Activity对象的onStop()方法已被调用)的进程。
这些进程对用户体验没有直接的影响,系统可能在任意时间终止它们,以回收内存供前台进程、可见进程及服务进程使用。
Empty process (空进程)
没有任何组件运行,所有的activity都关闭了,任务栈清空了。不含任何活动应用程序组件的进程。
保留这种进程的唯一目的就是用作缓存,以改善下次在此进程中运行组件的启动时间。
为了在进程缓存和内核缓存间平衡系统整体资源,系统经常会终止这种进程。
2.服务两种启动方式
- startService
- 开始服务,会使进程变成为服务进程
- 启动服务的activity和服务不再有关系
- bindService
- 绑定服务不会使进程变成服务进程
- 绑定服务,是activity与服务建立连接,如果activity销毁了,服务也会被解绑并销毁,但是如果服务被销毁,activity不会被销毁
3.startService开启服务
- startService:开启并创建一个服务,服务长期运行在后台;
- 服务被创建时调用onCreate、onStartCommand;
- 服务只能被创建一次,但是可以开启多次onStartCommand;
- 服务被开启后,会在设置页面里面的running里面找得到这个服务;
- 服务会在后台长期运行,直到用户手工停止或者调用StopService方法,服务才会被销毁。
- stopService:停止服务,销毁服务对象;
- 服务只能被停止一次;
- 没有onPause、onStop、onResume、onRestart方法,因为service没有界面,长期运行在后台。
- 生命周期:
- onCreate:服务被创建的时候调用这个方法
- onStartCommand:开启服务
- onDestroy:销毁服务
onCreate->onStartCommand ->onDestroy
3.bindService方式开启服务
- bindService:绑定服务,可以调用服务里面的方法;
- 服务是在被绑定的时候被创建,调用oncreate、onbind方法;
- 服务不能再设置页面里面找到 ,相当于是一个隐形的服务
- 当绑定服务的activity销毁的时候,服务也销毁。
- unBindService:解除服务,停止服务里面的方法;
- 服务只能被解除一次,解除绑定的时候调用onUnbind、onDestrory方法,如果多次解除绑定会抛出异常;
生命周期:
- onBind:服务被绑定调用这个方法
- onUnbind:服务解除绑定调用这个方法
onCreate->onBind->onUnbind->onDestroy
为什么要引入bindService
目的为了调用服务里面的方法
4.通过bindservice方式调用服务方法里面的过程
步骤:
1、在服务类中创建一个代理人MyBinder,继承了Binder,Binder实现了IBinder接口:public class MyBinder extends Binder{ }
2、在服务类里面创建了一个MyBinder的成员变量:
private MyBinder myBinder;
3、在MyBinder类中写一个方法用于调用服务的业务逻辑方法:
public class MyBinder extends Binder{ //使用代理人调用服务里的方法 public void callMethodInService(){ methodInService(); } }
4、在activity中bindService时,定义了ServiceConnection,在这个连接中实现了两个方法:
private class MyConn implements ServiceConnection { /** * 服务连接成功时调用这个方法 */ @Override public void onServiceConnected(ComponentName name, IBinder service) { //得到服务绑定成功后返回的代理人MyBinder对象 myBinder = (MyBinder) service; } /** * 服务断开成功时调用这个方法 */ @Override public void onServiceDisconnected(ComponentName name) { } }
5、绑定服务
Intent intent = new Intent(this, TestService.class); //绑定服务时要求传入一个ServiceConnection实现类的对象 bindService(intent, new Myconn(), BIND_AUTO_CREATE);
6、通过在activity中通过代理人调用服务的业务逻辑方法:
myBinder.callMethodInService();
5.绑定服务抽取接口
接口(interface): 对外开放暴露的功能,但是不会暴露功能实现的细节;
让代理人实现服务接口的目的:只对外暴露接口里面业务逻辑方法,隐藏代理人里面的其他方法;步骤:
1、创建一个服务的接口类,里面包含需要对外暴露的业务逻辑方法:
public interface IService { public void callMethodInService(); }
2、让服务中的代理人实现服务的接口类:
private class MyBinder extends Binder implements IService{ //(实现服务接口中的方法)使用代理人调用服务里的方法 public void callMethodInService(){ methodInService(); } }
3、在activity中声明接口的成员变量:
private IService myBinder;
4、强制转换成服务的接口类型
private class MyConn implements ServiceConnection { /** * 服务连接成功时调用这个方法 */ @Override public void onServiceConnected(ComponentName name, IBinder service) { //强制转换成服务的接口类型 myBinder = (IService) service; } }
5、绑定服务
Intent intent = new Intent(this, TestService.class); //绑定服务时要求传入一个ServiceConnection实现类的对象 bindService(intent, new Myconn(), BIND_AUTO_CREATE);
6、在activity中通过接口的成员变量调用服务的业务逻辑方法:
public void call(View view){ myBinder.callMethodInService(); }