Service 总结

认识 Service 的误区

Service作为Android四大组件之一,它的主要作用是在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。

注意:这里的后台是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。并且要注意 Service 是运行在主线程里的、 Service 是运行在主线程里的、Service 是运行在主线程里的;也就是说如果你在Service里编写了非常耗时的代码,程序必定会出现ANR的。另外:只有 Activities、Services 和 Content Providers 可以绑定到服务 — 您 无法 从广播接收器绑定到服务。

那么我们要想让 service 在后台处理耗时操作怎么做呢?很简单起个线程就可以了!

生命周期

1、如果通过 startService() 启动,多次点击启动服务的话,onCreate()只在创建 service 时执行一次,其他时候都是只走onStartCommand(),对于 onBind()方法返回 null 即可。销毁的时候,在service里面的话,可以直接用stopSelf(),在Activity中时用stopService()即可!

注意:这种情况下 Service 和 Activity 无任何关系,所以Activity的销毁是 不影响 Service 的生命周期的

2、如果通过 bindService() 启动,多次点击绑定服务的话,只走一遍 onCreate()和onBind() ,不会再执行onStartCommand(),但是此方式启动的话,onBind() 里需要返回一个Binder对象,这个对象可以直接通过继承 Binder 类来实现。因为是和Activity绑定启动的,所以需要在Activity中实现 ServiceConnection 接口 并通过 onServiceConnected() 把 Binder对象 传递到Activity中,以便后续 Activity 操作 Service 。销毁的时候,需要判断Binder对象是否存在,存在的话调用 onUnbind() 销毁Service 并置空Binder对象。

注意:这种情况下 Service 和 Activity生命周期紧密相关,Activity 销毁时,如果Service没有解绑,则需要进行解绑(流程同上面的销毁的时候一样),否则报异常:android.app.ServiceConnectionLeaked: Activity com.test.sang.mytest.GeneralServriceActivity has leaked ServiceConnection 。

3、如果通过 startService() 启动,又通过bindService() 启动的话,生命周期执行顺序 onCreate() -> onStartCommand() -> onBind() ,销毁的时候,需要 stopService() 和 onUnbind() 都调用了才会执行销毁,单独使用其中一个方法的话Service不会被销毁 。即在 Activity 销毁时只调用了 onUnbind() 的话,Service还是会在后台运行的,再次进入 Activty 进行 bindService() 绑定时,ServiceConnection 中的 onServiceConnected() 会重新连接,但是 onBind() 不会在走!

远程 Service

远程Service其实非常简单,只需要在 AndroidManifest 中注册 Service 的时候将它的android:process属性指定成 :remote就可以让 Service 运行在另一个进程了。为了确认下是否已经运行在另外一个进程当中了,我们可以分别在Activity的 onCreate() 方法和 Service 的 onCreate()方法里加入一行日志打印出各自所在的进程 id(id获取通过改方法 Process.myPid() ), 至于生命周期在上面已经说过了,不再赘述了哈!

远程 Service 与 Activity 通信,就没有上述的那么简单了,如果直接在 Activity 中去 bindService() 进行绑定启动的话,应用会直接崩溃,原因很简单就是上面说的,远程Service在另一个进程,它已经脱离了 Activity 所在的进程。Service 和 Activity运行在两个不同的进程当中,这时就不能再使用传统的建立关联的方式,程序也就崩溃了。

那么如何才能让Activity与一个远程Service建立关联呢?——使用AIDL来进行跨进程通信(IPC)

AIDL(Android Interface Definition Language)是Android接口定义语言的意思,它可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

首先需要新建一个AIDL文件,在这个文件中定义好 Activity 需要与 Service 进行通信的方法。新建 MyAIDLService.aidl 文件,代码如下所示:

// MyAIDLService.aidl
package com.test.sang.mytest.aidl;

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

interface MyAIDLService {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    String showMsg(String msg);
}

然后修改 远程Service 的Binder对象的生成(跟普通 service 的 Binder对象生成不同),部分代码如下:

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind executed");
        return mBinder;
    }

    MyAIDLService.Stub mBinder = new MyAIDLService.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public String showMsg(String msg) {
            return msg;
        }
    };

在 Activity 中需要实现 ,才能绑定启动 Service,核心代码如下:

    //实现ServiceConnection
    ServiceConnection remoteServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MyAIDLService myAIDLService = MyAIDLService.Stub.asInterface(service);
            try {
                myAIDLService.showMsg("跨进程服务");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            //TODO 服务断开连接时的一些操作
        }
    };

    /**
     * 调用远程 service
     */
    private void bindRemoteService(){
        Intent remoteIntent = new Intent(this, TestRemoteService.class);
        bindService(remoteIntent, remoteServiceConnection, Service.BIND_AUTO_CREATE);
    }

这样就把远程Service端的工作全部完成了,就可以进行自身应用的绑定服务了!

如果是其他应用的Activity如果想要和 TestRemoteService (即上面应用的远程service) 建立关联其实也不难,后续补上!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值