Service

Service

--------------首先要创建服务,必须创建 Service 的子类,同时重写一些回调方法;

package com.example.demoservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service {

    private MBinder mBinder = new MBinder();

    class MBinder extends Binder {
        public void getService() {
            Toast.makeText(MyService.this, R.string.get_service_success, Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(MyService.this, R.string.service_create, Toast.LENGTH_SHORT).show();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(MyService.this, R.string.service_start_command, Toast.LENGTH_SHORT).show();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(MyService.this, R.string.service_destroy, Toast.LENGTH_SHORT).show();
    }

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

onBind():当另一个组件想通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。在此方法的实现中,必须返回一个IBinder 接口的实现类,供客户端用来与服务进行通信。无论是启动状态还是绑定状态,此方法必须重写,但在启动状态的情况下直接返回 null。

onCreate():首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或onBind() 之前)。如果服务已在运行,则不会调用此方法,该方法只调用一次。

onStartCommand():当另一个组件(如 Activity)通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法,服务即会启动并可在后台无限期运行。 如果自己实现此方法,则需要在服务工作完成后,通过调用 stopSelf() 或 stopService() 来停止服务。(在绑定状态下,无需实现此方法。)如果希望服务一旦启动就立刻执行某个操作,可以讲逻辑写在这里。

onDestroy():当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等,这是服务接收的最后一个调用。销毁服务时,应该在onDestroy()方法中去回收那些不再使用的资源。

------------------如何让Activity与Service通信?实现ServiceConnection注意点?

Activity是通过实现 ServiceConnection 接口来与服务建立连接的,它包含以下两个方法:
onServiceConnected(ComponentName name, IBinder service):服务绑定成功后,会回调该方法;若服务异常中断后重启,也会重新调用该方法;
onServiceDisconnected(ComponentName name)服务异常解绑\终止后调用该方法注意,unbindService()不会调用该方法;

服务是通过实现 IBinder onBind(Intent intent) 方法来转换为 onServiceConnected() 方法所需要的 IBinder 型的 service 参数的。

-------------创建 ServiceConnection 实例:

 /**
     * 将IBinder类的对象iBinder向下转型成MyService.MBinder类的对象binder,形成一个connection
     */
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            binder = (MyService.MBinder) iBinder;
            Toast.makeText(MainActivity.this, R.string.service_connect_success, Toast.LENGTH_SHORT).show();
            binder.getService();
            mServiceConnect = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Toast.makeText(MainActivity.this, R.string.service_disconnect, Toast.LENGTH_SHORT).show();
            mServiceConnect = false;
        }
    };

----------------绑定服务:

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

1. service是什么?

service是一个服务,可以在后台执行长时间运行操作而没有用户界面的应用组件,可以用activity和broadcast启动,service只要启动就会在后台一直运行,哪怕启动他的activity已经被销毁也不会受影响,当然也可以绑定activity可以与ACitivy进行通讯,service是运行在主线程中,不能做耗时操作

2. Service的生命周期?bindService和startService?

只是用startService()启动服务:onCreate() -> onStartCommand() -> onDestory(stopService()/stopSelf)
只是用bindService()绑定服务(获取一个服务持久连接):onCreate() -> onBind() -> onUnBind() ->onDestory
即调用startService()启动服务又调用了bindService()绑定服务,必须同时调用stopService()和unbindService():onCreate() -> onStartCommnad() -> onBind() -> onUnBind() -> onDestory

3. Service有哪几种启动方式?

startService:

如果一个Service被某个Activity 使用 startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行,但它依旧运行于main线程。如果这个Service被startService方法多次启动,那么onCreate方法只会调用一次,onStartCommand将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例。该Service将会一直在后台运行,即使启动它的Activity已经退出,它直到某个activity调用stopService,或自身调用的stopSelf方法才会结束服务当然如果系统资源不足,android系统也可能结束服务。

bindService():

如果一个Service被某个Activity 调用 bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStartCommand()方法不会被调用。当连接建立之后,Service将会一直运行,除非调用unbindService 方法断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候)系统才会自动停止Service,对应onDestroy将被调用。(unbindService 不会调用onDestory)

还有一中复杂用法,就是同时使用startService和bindService方式启动服务。如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须由外界的activity调用 stopService 或 Service自身调用stopSelf 来停止服务

4. 多次启动Service,一次stop,Service是否还存在?多次绑定Service,一次unbind,Service是否还存在?

StartService是一对一的,多个Activity多次启动或单个Activity单次Service,一次stop,Service不存在
bindService是多对一的,多个Activity多次绑定Service,一次unbind,Service存在

6. IntentService

Service中的代码都是默认运行在主线程中,为了避免ANR,应该在Service的具体执行方法中开启一个子线程。为了可以简单地创建一个异步、会自动停止的Service,Android专门提供了一个IntentService类

public class MyIntentService extends IntentService {

    public MyIntentService(){
        //调用父类的有参构造函数
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //在这里处理耗时操作,当执行完成后会自动停止Service
    }
}

IntendService使用场景:

IntentService相比父类Service而言,最大特点是其回调函数onHandleIntent中可以直接进行耗时操作,不必再开线程。其原理是IntentService的成员变量 Handler在初始化时已属于工作线程,之后handleMessage,包括onHandleIntent等函数都运行在工作线程中。

如果对IntentService的了解仅限于此,会有种IntentService很鸡肋的观点,因为在Service中开线程进行耗时操作也不麻烦。我当初也是这个观点,所以很少用IntentService。

但是IntentService还有一个特点,就是多次调用onHandleIntent函数(也就是有多个耗时任务要执行),多个耗时任务会按顺序依次执行。原理是其内置的Handler关联了任务队列,Handler通过looper取任务执行是顺序执行的。

这个特点就能解决多个耗时任务需要顺序依次执行的问题。而如果仅用service,开多个线程去执行耗时操作,就很难管理。

例如在之前做的app中,有一个需求是下载某段时间用户保存的图片,下载完成后显示在imageView中;一般需要下载的图片有很多,每下一个图片就是一个线程,下载完后立即显示出来,所以肯定希望下载是按顺序依次下载,这样用户体验就比较好。当时的处理方式欠妥,直接开多个线程去下载,在前一个图片下载完成之前,其他线程必须等待;这样虽然也可以实现功能,但效率上不高,甚至可能出现ANR(具体代码逻辑是,如果后面的线程获得了cpu,而前面的图片还没下完,则等待;假设前一张图片没下完,而后面的线程一直获得cpu,就有问题)。

如果这个场景使用IntentService就非常方便,每个耗时任务都按顺序依次执行,不必担心出现逻辑上或性能上的问题,也是IntentService的价值所在。

总结:Android中很多类都是为某些常用场景所设计,例如本文中的IntentService以及之前写过的handlerThread等类,平时多积累,在以后遇到一些棘手问题时才能迎刃而解。

7. 哪些是前台服务?哪些是后台服务?

Service几乎都是在后台运行的,一直以来它都是默默地做着辛苦的工作。但是Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service。如果你希望Service可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台Service。前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service.


8. 如何提高Service的优先级?

--------添加android:persistent=“true”
--------设置onStartCommand()的返回值
--------startForeground()提高service的进程等级

9. Service的onStartCommand方法有哪几种返回值?各代表什么意思?

START_STICKY:kill后会被重启,但是重启后调用onStarfCommand()传进来的Intent参数为null,说明被kill的时候没有保存Intent;

START_STICKY_COMPATIBILITY:START_STICKY的兼容版,但是不能保证onStartCommand()方法被调用,如果应用程序的targetSdkVersion 小于 2.0版本,就会返回该值,否则返回START_STICKY,同时再次启动时只会调用onCreate(),不保证能调用onStartCommand()方法

START_NOT_STICKY:kill之后不会被重启;

START_REDELIVER_INTENT:kill后会被重启,同时重启调用onStartCommand()时再次传入保存的Intent。

10. Activity调用Service中的方法有哪几种?

Binder对象,aidl, Messenger

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值