Android 四大组件之Service

---恢复内容开始---

1,Service的生命周期

onCreate第一次创建service的时候调用。

onStartCommand启动service的时候调用。

onStart(This method was deprecated in API level 5. Implement onStartCommand(Intent, int, int) instead.

onDestroy销毁的时候调用。

2,进程优先级(由高到低):(红色字体的两个进程是经常被系统回收的两个进程)
    1. Foreground process 前台进程 用户正在操作的应用程序的进程.

    2. Visible process    可视进程  用户可以看到, 但无法进行操作的应用程序的进程.

    3. Service process    服务进程  后台运行的服务所在的进程.(如果有Activity再前台,则该进程属于前台进程)

    4. Background process 后台进程  最小化应用程序, 托管到后台运行.

    5. Empty process      空进程    已经退出的程序, 没有任务在运行.

3,service的使用注意事项:

  1.是否可以在service里写一些费时操作? 不能。如果有耗时操作可能会导致ANR的发生。 (onReceive方法内是否可以写耗时操作?原因)
       原因是:service这些回调方法的代码是运行在主线程上的。

  2.IntentService 该服务已经启动了一个线程,你不必再启动了。你要做的事情直接写到onHandleIntent,它会在子线程里处理。

三道面试题:

  1. service和activity的区别。
    • activity可以和用户交互,service可以在后台做些事情而不用跟用户交互。
    • activity在退出程序后会退出,而对于service,如果没有显示的调用停止服务,那么服务就没有结束,它仍在后台运行。
    • 最大的区别应该是:没有服务运行的后台进程叫后台进程,而有服务的后台进程叫服务进程。安卓系统的内存回收经常会回收掉优先级低的后台进程。
  2. 既然程序已经退出,为什么还保留空进程?
    • 优化用户体验。当用户下次启动该APP的时候,无需重新给分配进程,节约时间,提高效率。只有当内存不足时采取回收资源。 
  3. service和线程都是在后台运行,那他们之间有什么关系?
    • service和线程不是一个范畴的东西。service是四大组件之一,是一个特殊的类,在service中可以另起线程。service本身不是运行在一个单独进程中,默认情况下service是运行在主线程中的。

service的具体使用:

  1. 在activity中启动service与停止service

  

1 //启动服务
2 Intent intent = new Intent(this,MyService.class);
3 startService(intent);
4 //停止服务
5 Intent intent = new Intent(this, MyService.class);
6 stopService(intent);

 

  2,activity通过绑定service,可以调用服务内的方法(activity如果关闭的话,service也会结束)

//在Activity中调用本地服务(同一个应用中的服务)中的方法:
//1.调用bindservice去绑定服务,传递一个连接桥对象
//2.在service内部去继承一个Binder,实现的子类 。该子类可以随意调用service内的方//法。
//3.在onBind方法中,返回该子类的实现。
//4.当绑定ok,连接桥建立成功之后,连接桥对象的onServiceConnected 会被调用到,  这里面会返回一个IBinder对象,该对象就是onBind返回的那个。
//5.拿到这个IBinder对象之后,强转为MyBinder接收,然后调用其方法即可。

//绑定和解绑服务
public void bindservice(View view){
        //绑定服务
        Intent intent = new Intent(this, MyService.class);
        myServiceConnection = new MyServiceConnection();
        bindService(intent, myServiceConnection, BIND_AUTO_CREATE);

    }

    public void unbindservice(View view){
        //解绑服务
        if(myServiceConnection!=null){
            unbindService(myServiceConnection);
        }
    }
    public void callLocalServiceMetod(View view){
        //调用本地方法
        if(binder!=null){
            Log.i("MyService","调用本地方法");
            final String callParentMethod = binder.callParentMethod();
            final int count = binder.getcount();
            Toast.makeText(this,callParentMethod+count,Toast.LENGTH_SHORT).show();
        }
    }
    class MyServiceConnection implements ServiceConnection{
        //服务建立起来的时候调用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if(service!=null){
                binder = (MyService.MyBinder) service;
            }
            Log.i("MyServiceConnection","onServiceConnected");
        }
        //服务连接断开的时候调用
        //onServiceDisconnected() 在连接正常关闭的情况下是不会被调用的, 该方法只在Service 被破坏了或者被杀死的时候调用.
        // 例如, 系统资源不足, 要关闭一些Services,
        // 刚好连接绑定的 Service 是被关闭者之一,  这个时候onServiceDisconnected() 就会被调用。
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i("MyServiceConnection","onServiceDisconnected");

        }
    }

//service方法
public class MyService extends Service {
    public int count;
    public boolean flag=true;
    public MyService() {
    }
    public String getName(){
        return "I am MyService";
    }
    class MyBinder extends Binder{
        //binder是用来传输数据的
        public String callParentMethod(){
            return getName();
        }
        public int getcount(){
            return count;
        }

    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("MyService", "onCreate");
        new Thread(){
            @Override
            public void run() {
                super.run();
                //一绑定上就开始做服务
                while(flag){
                    count++;
                    try {
                        Thread.sleep(1000);

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i("通过绑定的服务开始了",""+count);
                }
            }
        }.start();
        //调用本地方法是的返回值
        return new MyBinder();
        //
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("MyService","onCreate");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("MyService", "onDestroy");
        flag=false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyService", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
}

      3,进程间通信(IPC)(Android使用一种接口定义语言AIDL(Android Interface Definition Language)来公开服务的接口的方式来暴露服务接口)

进程间通信实现过程: 
1. 定义服务类.
2. 定义aidl接口文件.
3. 在服务中onbind方法中返回实现aidl接口stub的对象.
4. 在另一个程序中调用bindService方法绑定服务.
5. 拷贝aidl接口文件(包括包名)到另一个程序中.
6. 在onServiceConnected方法中把Ibinder对象转换成aidl接口对象.
7. 使用接口对象调用方法(至此调用到远程服务的方法, 实现进程间通信)

//被调用的远程service
//接口
package com.rgd.day16_bindservice;

// Declare any non-default types here with import statements

interface MyAIDLInterface {
   String callParentMethod();
   int getcount();
}
//远程service要写的
class MyBinder2 extends MyAIDLInterface.Stub{
        @Override
        public String callParentMethod() throws RemoteException {

            return getName();
        }

        @Override
        public int getcount() throws RemoteException {
            return count;
        }
    }
//本地调用要写的
class MyConnection implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if(service!=null){
                binder = MyAIDLInterface.Stub.asInterface(service);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    public void bindremoteservice(View view){
        //绑定远程服务
        Intent intent = new Intent();
        intent.setAction("com.ren.myservice");
        intent.setPackage("com.rgd.day16_bindservice");
        myConnection = new MyConnection();
        bindService(intent, myConnection,BIND_AUTO_CREATE);

    }

    public void unbindremoteservice(View view){
        //解绑远程服务
        if(myConnection!=null){
            unbindService(myConnection);
        }
    }

    public void callremoteServiceMetod(View view){
        //调用远程服务的方法
        if(binder!=null){
            try {
                String s = binder.callParentMethod();
                int getcount = binder.getcount();
                Toast.makeText(this,s+getcount,Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }

    }

 

 

               

posted @ 2016-03-14 23:32  鸡毛落一地  阅读(283)  评论(0编辑  收藏  举报