Service的使用

2018-01-23  本文已影响0人  笔墨Android

不怕跌倒,所以飞翔

本文讲解内容:

1.Service的简单使用

1.1普通Service的简单使用

后台服务的优先级是很低的,当系统内存不足的时候就会被回收.

1.1.1 创建服务

创建服务的方法就不写了,这里主要说 明一下AndroidManifest中的属性

1.1.2重写相应的方法

public class GeneralService extends Service {
    private String TAG = GeneralService.class.getSimpleName();

    public GeneralService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        /*这个是绑定Binder的相应的方法,
          *这个服务中先不去考虑
          */
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        /*
        * 创建服务的时候调的回调
        * 这个方法只有在创建Service的时候执行一次
        */
        Log.e(TAG, "服务创建了");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        /*
        * 具体执行逻辑的时候的方法
        * 1.这里有一点问题说明一下,有的时候你创建相应的服务了,但是由于后台资源不足,服务被销毁了
        * 这个时候,在执行的时候就会存在相应intent为空的情况,当你遇到这个情况的时候,只要返回相应的标识就可以了
        *  return Service.START_REDELIVER_INTENT;就能保证服务再次启动的时候intent不为空了
        * 2.这个方法每次调用相应的startService都会去执行
        */
        Log.e(TAG, "服务正在执行");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        /*
        * 销毁服务的回调
        * 这个方法只有在销毁Service的时候执行一次
        */
        Log.e(TAG, "服务销毁了");
    }
}

1.1.3启动/关闭服务

1.1.4这里着重介绍一下相应得方法

相应的执行逻辑:

  1. 正常的生命周期逻辑(第一次启动)
    构造方法()->onCreate()->onStartCommand()->onDestory();
  2. 当Service存在的情况下再次启动
    onStartCommand()

也就是说如果多次点击启动,onCreate()不会多次执行,只有Service销毁的时候再次启动的时候才会执行相应的onCreat()方法,简单理解就是onCreat()方法只有在创建的时候执行一次!

1.2IntentService的简单使用

使用上和上面的内容没有什么出入,只是继承的方法和内部相应的实现有点变化,但是变化不是很大,这里就贴一下相应的内容,不去做相应的具体讲解了,只要记住这个Service能自己调用相应的onDestory()就可以了.

public class IntentService extends android.app.IntentService {
    private String TAG = IntentService.class.getSimpleName();

    public IntentService() {
        super("IntentService");
        /*调用父类的构造方法,这里面传入的名字是工作线程的名称,所以这个名称你可以随便传*/
        Log.e(TAG, "服务有名字了");
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "服务创建了");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        /*
         * 在我的理解,这个工作线程只会有一个,因为里面维护了一个相应的Handler
         * 每次的耗时操作都会以相应的队列的方式在IntentService中一次执行
         * 每次开启服务的时候都会走这个方法,但是我调用相应的Stop无法停止相应的服务
         * 这个还有待于研究,因为子停止,或许不需要停止的相应的方法吧(反正相应的停止的方法是不好使的)
         */
        for (int i = 0; i < 100; i++) {
            Log.e(TAG, "服务正在执行" + i);
        }
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        /*这个方法实在o'nHandleIntent之前进行执行
          *所以这里可以初始化一些相应的内容
          */
        Log.e(TAG, "onStartCommand: 执行了");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        /*这个方法会在相应的onHandleIntent执行完成的时候回调*/
        Log.e(TAG, "服务销毁了");
    }
}

相应的启动方法类似.

但是这里要注意几个问题:

  1. 当你startService的时候,即使你调用相应的stopService也不会让Service停止下来
  2. 这个服务不存在相应的stopService的方法了

剩下的基本上注释都有.

2.绑定服务的方法

你可能会发现,上面的方法只是启动了服务,但是其实Service和Activity其实根本没有什么关联,在Activity也没有办法去控制Service里面的执行内容,也就是Service脱离了相应的Activity,只是通过Activity启动而已,这个不是我们想看到的,所以才有相应的绑定方法来控制Service.

2.1 绑定服务的写法

上面在开启服务的时候,不知道大家有没有注意到一个细节在onBind()方法中我们返回的是空,为什么这里返回的是空呢???其实这个就是绑定服务所要必须的内容.下面我们开始实现简单的内容吧!

2.1.1创建相应的Binder对象

    class MyBinder extends Binder {
        public void startBinder() {
            Log.e(TAG, "startBinder: ");
        }

        public void stopBinder() {
            Log.e(TAG, "stopBinder: ");
        }
    }

这里面的方法你可以随便的写,想要什么写什么!!!

2.1.2在相应的Service中创建相应的对象,并在Binder()中返回

    private MyBinder mMyBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mMyBinder;
    }

2.1.3启动相应的Service

这个也是这里的重点问题,涉及到一个ServiceConnection

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            /*这个方法会在相应的创建的时候进行调用*/
            Log.e(TAG, "onServiceConnected:  连接创建的时候调用");
            //向下转型从而调用相应的方法
            BindService.MyBinder binder = (BindService.MyBinder) service;
            binder.bindService();
     }

        @Override
        public void onServiceDisconnected(ComponentName name) {
           /*这个方法是在Service丢失的情况下才被调用
            * 或者在Service被杀死的视乎调用*/
        }
    };

说明一下上面两个回调方法:

     //绑定
        Intent intent = new Intent(this, BindService.class);
        /*参数三有必要说明下:
         *BIND_AUTO_CREATE 这个方法是创建关联后自动创建Service,会使得相应Service中的onCreate()方法的到执行
         * 但相应的onStartCommand()不会被执行
         */
        bindService(intent, mConnection, BIND_AUTO_CREATE);
   
     //解绑
        unbindService(mConnection);

2.1.3BindService的生命周期

构造方法->oncreate()->onBind()->onServiceConnected()
当你再次点击的时候不会调用相应的启动的流程了,除非你调用unBind()方法进行相应的取消否则不会去创建的,这里只是创建了连接,让Activity持有了相应的Service可以使用内部的相应方法了!

3.Service的声明周期

这里有一个问题是你需要注意的,如果你想在onStartCommand()想结束Service的话,直接调用stopSelf()方法就可以了

3.1几种特殊情况下的生命周期问题

4.一些服务的特殊使用方法

开机启动服务(其实这个思路很简单,监听开机的广播,然后启动你的服务就可以实现了),下面直接上代码:

public class BootBroadcastReceiver extends BroadcastReceiver {
    private static final String mBootAction = "android.intent.action.BOOT_COMPLETED";
    private static final String mShutDownAction = "android.intent.action.ACTION_SHUTDOWN";
    private static final String TAG = BootBroadcastReceiver.class.getSimpleName();
    private Intent mServiceIntent;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent == null) return;
        if (intent.getAction().equals(mBootAction)) {
            Log.e(TAG, "onReceive: 监听到开机广播了");

            /*这里启动服务*/
            mServiceIntent = new Intent(context, MyService.class);
            mServiceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startService(mServiceIntent);

        } else if (intent.getAction().equals(mShutDownAction)) {
            Log.e(TAG, "onReceive: 监听到关机广播了");
            if (mServiceIntent != null) {
                /*这里关闭服务*/
                context.stopService(mServiceIntent);
            }
        }
    }
}
        <receiver
            android:name=".BootBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <!--开机广播-->
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
            <!--关机广播-->
            <intent-filter>
                <action android:name="android.intent.action.ACTION_SHUTDOWN"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>

其实上面的内容加起来就可以启动相应的广播了,但是一定要注意一点就是监听开机广播的时候涉及到权限的问题

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

这个问题千万别忘了...

上一篇下一篇

猜你喜欢

热点阅读