开始填坑了,刚开始肯定也是从最基本的东西开始撸,其实东西最后要归根究底都没有什么最基础的,总之是一次自我复习的过程,能够发散多少也要看了。为了不显得特别零散,尽量保持一篇一个主题吧,内容保持问答的方式,也供人产生更多发散。
1.Service有几种启动方式?
Service是一个专门在后台处理长时间任务的Android组件,它没有UI。它有两种启动方式,startService和bindService。
startService只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf或者其他组件调用stopService服务才会终止。
bindService方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBind操作,当发现所有绑定都进行了unBind时才会销毁Service。
在这里再附上一张service的生命周期
2.bindService是怎么进行绑定的?
和startService一样,bindService需要这样传参数:bindService(bindIntent, connection, BIND_AUTO_CREATE);
,一个参数和startService传入的Intent一样,第二个参数是一个ServiceConnection的匿名类对象,一般可以如下声明
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
myBinder.startDownload();
}
};
所以在需要启动的Service里面的onBind
方法就不能返回null了
private MyBinder mBinder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
class MyBinder extends Binder {
public void startDownload() {
Log.d("TAG", "startDownload() executed");
// 执行具体的下载任务
}
}
在onServiceConnected
里面返回的这个IBinder
对象就是service中定义的那个,所以相当于是activity拿到了service暴露的方法接口,然后想怎么浪都随意了。
第三个参数参考一下,一般用第一个flag
BIND_AUTO_CREATE表示当收到绑定请求时,如果服务尚未创建,则即刻创建,在系统内存不足,需要先销毁优先级组件来释放内存,且只有驻留该服务的进程成为被销毁对象时,服务才可被销毁;
BIND_DEBUG_UNBIND通常用于调试场景中判断绑定的服务是否正确,但其会引起内存泄漏,因此非调试目的不建议使用;BIND_NOT_FOREGROUND表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行,该标志位在Froyo中引入。
3.bindService和startService的使用场景和注意事项?
- 使用startService方式来启动Service时,生命周期是
onCreate
–>onStartCommand
,当在stopService之前多次startService会执行多次onStartCommand
,但之后执行一次onCreate
,使用stopService
之后会调onDestroy
。 - 使用
bindService
生命周期是onCreate
,不会走onStartCommand
,绑定成功会回调传入ServiceConnection
的onServiceConnected
的方法。 bindService
一旦绑定成功就相当于activity和service进行了一次连接,要么主动unBindService
,要么actvity销毁的时候也会自动解绑。一个service可以和多个activity进行绑定,相当于多个activity可以功能操作一个service,这个也是bindService的精髓了,当所有activity和service解绑了,这个service也会销毁。- 如果我们既点击了Start Service按钮,又点击了Bind Service按钮,不管你是单独点击Stop Service按钮还是Unbind Service按钮,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,点击Stop Service按钮只会让Service停止,点击Unbind Service按钮只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。
4.Service的onCreate回调函数可以做耗时的操作吗?
Service和Thread之间没有任何关系,Service中执行的代码也都是在主线程中执行的。
所以答案是不能。
使用Service主要是满足多个activity关注一个后台事件(比如下载,心跳,横竖屏切换状态恢复等)和一些其他需求(多进程,多APP间通信等),一定要和多线程区分开。
Service处理耗时操作同样是需要自己新开子线程来处理的,或者直接使用IntentService,可以直接在onHandleIntent
方法里面处理耗时操作,里面东西设计到Handler的一些机制,后面有机会可以分析下,现在就不跑偏了。
5.Service的保活策略
APP保活永远都是一场博弈论,Service保活作为一个小小分支主要也是了解了解。
- 将 Service 设置为 START_STICKY,利用系统机制在 Service 挂掉后自动拉活。
- 在service 的onDestory里面重启服务。
创建前台Service。
可以通过以下方式来创建一个前台Service
```
public class MyService extends Service {public static final String TAG = “MyService”;
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {super.onCreate(); Notification notification = new Notification(R.drawable.ic_launcher, "有通知到来", System.currentTimeMillis()); Intent notificationIntent = new Intent(this, MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.setLatestEventInfo(this, "这是通知的标题", "这是通知的内容", pendingIntent); startForeground(1, notification); Log.d(TAG, "onCreate() executed");
}
………
}
```
6.Service进程间通信
前面说到Service中执行耗时操作会阻塞UI线程导致ANR的,但是在注册Service的时候声明一下android:process=":remote"
就不会ANR了。
因为这样Service就会运行到其他进程中,虽然还是阻塞了线程,不过倒不会影响到界面中去。
但是这种情况想要通过bindService来启动就万万不行了,华丽丽地会挂吧。
针对于Service进程间通信安卓给出了很好的解决方案—AIDL。
这种进程间(也可以是APP间)的通信方案在很多地方都有用武之地的,一般都是Messenger&AIDL。
大概流程就是自定义AIDL接口,系统会自动生成对应的JAVA类,这个类作为binder的子类可以通过bindService的方式传给activity,需要注意以下几点:
- 在两个APP中都是用同一份AIDL文件,然后通过bindService的方式就可以进行通信,主要包名路径名也需要是一样的。
- 再不同APP中,bindService的第一个参数那个intent需要使用隐式的action来启动,5.0后系统不允许隐式启动service,不过并没什么关系,网上搜索是有解决方案的。
- AIDL一般只能传递Java的基本数据类型、字符串、List或Map,传递自定义类型可以实现Parcelable接口。
参考博客
http://blog.csdn.net/guolin_blog/article/details/11952435
http://www.jianshu.com/p/7a7db9f8692d?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=qq
http://blog.csdn.net/lmj623565791/article/details/47143563
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至same4869@126.com