Service的要点

1、startService()和bindService()两种方式启动

2、生命周期

3、IntentService与Service的区别

4、提高service的优先级

5、Activity 调用 Service 中的方法都有哪些方式

startService()和bindService()两种方式启动
  • started

其它组件调用 startService()启动一个 Service。一旦启动,Service 将一直运行在后台,即使启动这个 Service 的组件已经被销毁。通常一个被 start 的 Service 会在后台执行单独的操作,也并不需要给启动它的组件返回结果。只有当 Service 自己调用stopSelf()或者其它组件调用 stopService()才会终止。

  • bind

其它组件可以调用 bindService()来绑定一个 Service。这种方式会让 Service 和启动它的组件绑定在一起,当启动它的组件销毁的时候,Service 也会自动进行 unBind 操作。同一个 Service 可以被多个组件绑定,只有所有绑定它的组件都进行了 unBind 操作,这个 Service 才会被销毁。bindService启动的服务和调用者之间是典型的client-server模式,client可以通过IBinder接口获取Service实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。

当然,Service 还可以同时在上述两种方式下运行。这涉及到 Service 的两个回调方法的执行: onStartCommand()(通过 start 方式启动一个 Service 时的回调方法。)、onBind() (通过 bind 方式启动一个 Service 回调的方法)。

无论通过那种方式启动 Service(start、bind、start & bind),任何组件(甚至其他应用的组件)都可以使用 Service。并通过 Intent 传递参数。当然,你也可以将 Service 在 AndroidMenifest.xml 文件中配置成私有的,不允许其他应用访问。

将 android:exported 属性设为 false,表示不允许其他应用程序启动本应用的组件,即便是显式 Intent 也不行(even when using an explicit intent)。这可以防止其他应用程序启动您的 Service 组件。

举个栗子:

 //绑定服务
 Intent bindIntern = new Intent(MainActivity.this,CounterService.class);
 bindService(bindIntern,serviceConnection, Context.BIND_AUTO_CREATE);
//创建服务连接实例
private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            counterService = ((CounterService.CounterBinder)iBinder).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            counterService = null;
        }
};
 //启动服务
 Intent startIntern = new Intent(MainActivity.this,CounterService.class);
 startService(startIntern);
Service的生命周期

这两条路径并不是毫不相干的。当调用 startService() 去 start 一个 Service 后,你仍然可以 bind 这个 Service。比如:当播放音乐的时候,需要调用 startService() 启动指定的音乐,当需要获取该音乐的播放进度的时候,又需要调用 bindService(),在这种情况下,除非 Service 被 unbind,此前调用 stopService() 和 stopSelf() 都不能停止该 Service。

IntentService与Service的区别

Service既不是线程,也不是进程,而是依附于主线程的一个组件。Service用于在后台处理一些逻辑业务,不需要和用户进行交互。

IntentService继承于Service,用于处理异步请求,调用startService(intent)方法后,将请求通过intent传递给intentService,intentService在onCreate方法中构建一个HandlerThread的子线程,用于处理传递过来的请求。通过HandlerThread单独开启一个线程来依次处理所有Intent请求对象所对应的任务。这样以免事务处理阻塞主线程(ANR)。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。

使用IntentService必须实现的函数

1、参数为空的构造函数:然后再在其中调用super("name")这种形式的构造函数。因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的

public myIntentService() {
    super("myIntentService");
   // 注意构造函数参数为空,这个字符串就是worker thread的名字
}

2、实现函数onHandleIntent:在里面根据Intent的不同进行不同的事务处理。

好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求。

总结:

Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。

会创建独立的worker线程来处理所有的Intent请求;

会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;

所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;

为Service的onBind()提供默认实现,返回null;

为Service的onStartCommand提供默认实现,将请求Intent添加到队列中,通过工作队列把intent逐个发送给onHandleIntent();

IntentService不会阻塞UI线程,而普通Serveice会导致ANR异常

Intentservice若未执行完成上一次的任务,将不会新开一个线程,是等待之前的任务完成后,再执行新的任务,等任务完成后再次调用stopSelf()

提高service的优先级

1、在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时实用于广播。

2、在onStartCommand里面调用 startForeground()方法把Service提升为前台进程级别,然后再onDestroy里面要记得调用stopForeground ()方法。

3、onStartCommand方法,手动返回START_STICKY。

4、 在onDestroy方法里发广播重启service。

service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service。(第三方应用或是在setting里-应用-强制停止时,APP进程就直接被干掉了,onDestroy方法都进不来,所以无法保证会执行)

5、监听系统广播判断Service状态。

通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活。

6、Application加上Persistent属性。

Activity 调用 Service 中的方法都有哪些方式

Binder:

通过 Binder 接口的形式实现,当 Activity 绑定 Service 成功的时候 Activity 会在 ServiceConnection 的类 的 onServiceConnected()回调方法中获取到 Service 的 onBind()方法 return 过来的 Binder 的子类,然后通过对象调用方法。

Aidl:

aidl 比较适合当客户端和服务端不在同一个应用下的场景。

Messenger:

它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。一个Messeger不能同时双向发送,两个就就能双向发送了

results matching ""

    No results matching ""