Service总结

服务

  • 就是默默运行在后台的组件,可以理解为是没有前台的activity,适合用来运行不需要前台界面的代码
  • 服务可以被手动关闭,不会重启,但是如果被自动关闭,内存充足就会重启

下载代码和播放音乐这种运行于后台的代码,必须要写在服务里面。

为什么呢?例如下载:

activity 其实也是可以在后台下载,但是,点返回键的时候,activity死掉了(activity被onDestory()不代表该APP进程会被销毁),进程还在,那么子线程就依然可以下载,但当进程被销毁的时候,下载就会中断了。那进程什么时候销毁呢?在内存不足的时候进程就会很有可能被销毁…这时候就会涉及到进程优先级的知识。

进程优先级

  1. 前台进程:拥有前台activity(onResume方法被调用)
  2. 可见进程:拥有可见activity(onPause方法被调用)
  3. 服务进程:不到万不得已不会被回收,而且即便被回收,内存充足时也会被重启
  4. 后台进程:拥有后台activity(activity的onStop方法被调用了),很容易被回收
  5. 空进程:没有运行任何activity,很容易被回收

服务:开启方式

1.Context.startService()

  • (重点)该方法启动的服务所在的进程属于服务进程
  • Activity一旦启动服务,服务就跟Activity一毛钱关系也没有了
  • 不论调用了多少次startService()方法,你只需要调用一次stopService()来停止服务。

  • 在需要开启服务的Activity中:

Intent intent = new Intent(this, MyService.class);
startService(intent);//开启
stopService(intent);//关闭

2.Context.bindService()

  • (重点)该方法启动的服务所在进程不属于服务进程
  • Activity与服务建立连接,Activity一旦死亡,服务也会死亡

*在需要开启服务的Activity中:

Intent intent = new Intent(this, MyService.class);
    MyServiceConn conn = new MyServiceConn();
    bindService(intent, conn, BIND_AUTO_CREATE);

    class MyServiceConn implements ServiceConnection{  //内部类,服务链接对象
    //连接服务成功,此方法调用
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub
        pb = (PublicBusiness) service;
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // TODO Auto-generated method stub

    }

}

MyService类内容:

public class MyService extends Service {

    //绑定时调用
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("bind方法");
        return null;
    }

    //解绑时调用
    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("unbind方法");
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        System.out.println("create方法");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        System.out.println("start方法");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        System.out.println("destroy方法");
        super.onDestroy();
    }
}

生命周期

1.ContextstartService启动服务的生命周期

onCreate()->onStartCommand()->onDestroy()
  • 重复的调用Context.startService()会导致onStartCommand()被重复调用,而onCreate()只会被调用一次

2.Context.bindService()绑定服务的生命周期

onCreate()->onBind()->onUnbind() -> onDestroy() 
  • 重复的调用Context.bindService(),只会走一次onCreate()->onBind()。同时也不能重复地解绑,启动后,只能解绑一次。

服务的混合调用(重点)

  • 先startService()、再bindService(),先解绑、再停止,比如:用服务实现音乐播放时,因为音乐播放必须运行在服务进程中,可是音乐服务中的方法,需要被前台Activity所调用,所以需要混合启动音乐服务先start,再bind,销毁时先unbind,再stop

onCreate()->onStartCommand()->onBind()->onUnbind()-> onDestroy() 

服务运行在主线程

 Service和其他的应用组件一样,运行在进程的主线程中。这就是说如果service需要很多耗时或者阻塞的操作,需要在其子线程中实现。

找领导办证(访问服务里面的方法)

  • 把服务看成一个领导,服务中有一个banZheng方法,如何才能访问?
  • 绑定服务时,会触发服务的onBind方法,此方法会返回一个Ibinder的对象给MainActivity,通过这个对象访问服务中的方法

  • 在服务中定义一个类实现Ibinder接口,以在onBind方法中返回

class ZhongJianRen extends Binder implements PublicBusiness{
public void QianXian(){
    //访问服务中的banZheng方法
    BanZheng();
}   
public void daMaJiang(){

}
}

public class MainActivity extends Activity {

    private Intent intent;
    private MyServiceConn conn;
    PublicBusiness pb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(this, LeaderService.class);
        //绑定服务时要求传入一个ServiceConnection实现类的对象
        conn = new MyServiceConn();
        //1.绑定领导服务
        bindService(intent, conn, BIND_AUTO_CREATE);
    }
//2.内部类,服务链接对象
    class MyServiceConn implements ServiceConnection{

        //连接服务成功,此方法调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //5. TODO Auto-generated method stub
            pb = (PublicBusiness) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

    }

    public void click(View v){
        //调用服务的办证方法
        pb.QianXian();
    }

}
LeaderService服务类:
public class LeaderService extends Service {

        @Override
        public IBinder onBind(Intent intent) {
            //3. 返回一个Binder对象,这个对象就是中间人对象
            return new ZhouMi();
        }

    //4.在服务中定义一个类实现Ibinder接口,以在onBind方法中返回
    class ZhouMi extends Binder implements PublicBusiness{
        public void QianXian(){
                banZheng();
            }

        public  void daMaJiang(){
                System.out.println("陪李处打麻将");
            }
        }

        public void banZheng(){
            System.out.println("李处帮你来办证");
        }
    }
把QianXian方法抽取到接口PublicBusiness中定义
public interface PublicBusiness {
        void QianXian();
    }

服务的分类

  • 本地服务:指的是服务和启动服务的activity在同一个进程中
  • 远程服务:指的是服务和启动服务的activity不在同一个进程中

AIDL

  • Android interface definition language
  • 进程间通信
    1. 把远程服务的方法抽取成一个单独的接口java文件
    2. 把接口java文件的后缀名改成aidl
    3. 在自动生成的PublicBusiness.java文件中,有一个静态抽象类Stub,它已经继承了binder类,实现了publicBusiness接口,这个类就是新的中间人(继承的时候直接:中间人类名Stub)
    4. 把aidl文件复制粘贴到06项目,粘贴的时候注意,aidl文件所在的包名必须跟05项目中aidl所在的包名一致
    5. 在06项目中,ServiceConnection对象链接类中的onServiceConnected()方法中强转中间人对象得到中间人对象:mService = IMusicService.Stub.asInterface(serviceIBinder);





你可能感兴趣的:(技术总结)