zoukankan      html  css  js  c++  java
  • Android中的Service小结

    简介

    Service适合执行不需要和用户交互,而且长期运行的任务。即使程序被切换回后台,服务仍然可以正常运行。Service并不自动开启线程,默认运行在主线程中。

    Service中需要重载的函数

    onCreate()方法在服务创建的时候调用。onBind()是Service中唯一的抽象方法,必须要在子类中实现。 onStartCommand()在每次启动服务(startService)的时候调用,可用于服务一旦启动就立刻去执行某个动作。

    onDestroy()在服务销毁(stopService)的时候调用,可用于收回资源

    在Activity中启动和停止服务

    可以通过Activity中的Intent来启动/停止Service

                    Intent startIntent = new Intent(this, MyService.class);
                    startService(startIntent);
                    break;
    
                    Intent stopIntent = new Intent(this, MyService.class);
                    stopService(stopIntent);
                    break;

    在Activity中控制Service

    需要创建一个类继承自Binder,然后在里面定义一些处理任务的函数。接着在MyService中创建这个类的实例,并在onBinder中返回。在Activity中创建ServiceConnection匿名类,覆盖onServiceConnected和onServiceDisconnected函数。这两个类在bind和unbind时被调用。

    Service的生命周期

    在Context中调用startService方法,相应的服务会自动启动,并回调onCreate->onStartCommand 在Context中调用bindService方法,可以获得一个服务的永久链接,并回调onCreate->onBind->onServiceConnected->onUnbind->onServiceDisconnected 销毁的时候不管调用了多少次onStartCommand只会调用一次onDestroy

    绑定的Service在被绑定的Activity退出的时候会自动解除绑定。

    向Service中传递数据

    如果是通过startService启动,在startService的参数Intent中,可以通过putExtra附加数据。在Service端,通过onStartCommand的第一个参数获取这个传过来的值。

    如果是通过bindService启动,在Service中的onBind函数会返回一个Binder对象,这个对象会在onServiceConnected中被返回。在Service的Binder对象中定义接口,在Activity中就可以调用。这种通过接口调用的方法要更高效。

    从Service中返回数据

     1, 在Service中定义callback

     2, 在onBind返回的Binder中添加getService函数,让Activity可以取得Service的实例。然后就可以调用Service的setCallBack方法来添加需要通知的函数接口。

    跨应用启动Service并传递数据:

    在Android5.0之前可以通过隐式intent启动服务,但是Android5.0之后不可以了, 启动Service的Intent必须是Explicit的。

    在两个Application之间是不可能获取到Service的定义的,需要调用SetComponent函数:

            serviceIntent = new Intent();
            serviceIntent.setComponent(new ComponentName("com.wanxiang.www.startservicefromanotherapp", "com.wanxiang.www.startservicefromanotherapp.AppService"));
            serviceIntent.putExtra("data", "Hello AppService");

    通过这种方法可以指定要启动的Service的Application,并且也同样可以传递数据过去。但是有个前提,被启动的这个Service所在的Activity必须在运行过程中的。

    同样也可以通过绑定服务来启动远程Service

                    bindService(new Intent(this, MyService.class), this, BIND_AUTO_CREATE);

    本地Activity中的onServiceConnected也会被执行:

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            System.out.println("Bind service");
            System.out.println(iBinder);
    }

    传递数据:

    首先在远程Activity的aidl目录中建一个本地Activity包名的目录,把本地Activity中的AIDL文件拷贝一份过去,可以在onBind()中返回这个接口的stub,并在这个接口中添加函数

    @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            return new IAppServiceRemoteBinderInterface.Stub() {
                /**
                 * Demonstrates some basic types that you can use as parameters
                 * and return values in AIDL.
                 *
                 * @param anInt
                 * @param aLong
                 * @param aBoolean
                 * @param aFloat
                 * @param aDouble
                 * @param aString
                 */
                @Override
                public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
    
                }
    
                @Override
                public void setData(String data) throws RemoteException {
                    AppService.this.data = data;
                }
            };
        }

    在远程Activity中的onServiceConnected函数中返回这个对象,并保存在类的实例变量中:

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            System.out.println("Bind service");
            System.out.println(iBinder);
            binder = IAppServiceRemoteBinderInterface.Stub.asInterface(iBinder);
        }
    
        private IAppServiceRemoteBinderInterface binder = null;

    然后就可以通过这个变量来调用AIDL中添加的函数,并传递数据给Service。

                case R.id.btnSync:
                    if (binder != null)
                        try {
                            binder.setData(etInput.getText().toString());

    前台Service

    后台的Service会被回收,可以通过在Service中定义Notification,并调用startForeground()来使Service始终保持前台运行。

    异步并且自动停止的服务

    Android提供了一个IntentService专门解决创建一个异步线程并自动停止的问题。

    只需要继承自这个类,并重写onHandleIntent方法,在这个方法里处理一些具体逻辑。这个方法运行在子线程里,不会造成ANR。

  • 相关阅读:
    帮人“解封微信”犯法?全国首例!判刑!
    热乎的校招面经试题解析——百度篇
    字节跳动入局在线教育:烧钱、亏钱
    TF-IDF 算法介绍
    Django ORM 常见查询条件
    Django中render和render_to_response的区别
    Python异步操作MongoDB --Motor的使用
    Java 如何抛出异常、自定义异常
    java项目中的classpath到底是什么
    maven里的modelVersion
  • 原文地址:https://www.cnblogs.com/dracohan/p/5837807.html
Copyright © 2011-2022 走看看