服务(Service)是一种后台解决方案,即某程序退出后,后台还执行着服务。非常适合那些不需要和用户交互而需要长期运行的任务。但是!不要被服务运行在后台的概念所迷惑,实际上服务并不会开启线程,所有代码默认运行在主线程!!
1.安卓多线程编程
更新UI上的数据,必须在主线程执行。否则就会出现异常。
解决方法:
简单来说就是:子线程完成任务后,想更新视图时,告诉主线程,主线程来操作。
可以使用:Message、Handler、MesssageQueue、Looper来实现。
每个线程只有一个MesssageQueue、Looper对象。
异步消息处理机制原理:
(2)服务的创建、启动和停止
使用Intent启动和停止
(3)服务与活动通信
每个服务在应用程序中是通用的,一个服务可以和其他任意一个活动绑定,而不单单是MainActivity一个活动。
通信的目的:在活动中指挥服务去干什么,服务就去干什么。
比如在Service中实现一个下载的功能。然后在Acitivity中指挥该Service什么时候开始下载,什么时候报告进度,什么时候停止下载等。
1.在Service中使用Binder对象来对下载功能进行管理。
Binder对象为DownloadBinder。
2.当一个活动和服务绑定之后,活动就可以去调用服务中Binder提供的方法了。
ServiceConnection中的两个方法,onServiceConnected()和onServiceDisconnected()会分别在与活动成功绑定和接触绑定时调用。
在onServiceConnected()中通过向下转型得到downloadBinder对象,然后通过该对象即可调用刚才在Service中的Binder中定义的下载方法了。
但是,到这里还没有真正将两者绑定!
下面使用Intent将来两者绑定:
关键点在于:bindService()和unbindService()两个方法。
bindService()方法的第一个参数为intent,第二个为connection,第三个为字段,代表绑定后自动创建该服务。
这样:当点击bind_service按钮时,执行bindService方法,bindIntent执行,活动就会和服务绑定,并执行connection中写好的下载功能。目标达成。
(4)服务的生命周期
上图中共三种情况(方法成对,不能搞混):
1.startService方法调用,启动这个服务,不管该方法被调用几次,只存在一个服务实例,所以只需要调用一次stopService或stopSelf方法就可以停下服务。
2.调用bindService方法启动服务,只要不断开连接,服务一直运行。使用unbindService方法断开绑定。
3.当既调用startService又调用bindService,要同时调用stopService和unbindService方法才能停止服务。
特别注意:使用startService启动服务后,调用unbindService会出错!他们不是一对的。
(5)其他技巧
1.使用前台服务
使用前台的原因:服务在后台干着累活,优先级比较低。当内存不足的时候,就可能会回收掉某些服务。如果我们期望某个服务一直运行,怕他倒霉,被回收掉,那么我们就可以考虑使用前台服务。
前台服务和普通服务的最大区别:会一直有一个正在运行的图标在状态栏显示。类似于通知。
2.IntentService
使用原因:服务默认运行在主线程,所以若在服务中执行耗时操作,则会使主线程出现堵塞。所以,要在服务中开线程来执行耗时的操作,这里就用到了本文开头所学习的安卓的消息异步处理机制。
结论:该IntentService类和Service类本质上没区别,都是服务类。但是本类帮我们开了一个新线程,可以在onHandleIntent中执行耗时的操作。并且完成后会在任务完成后,调用onDestroy关闭服务。简化了程序员的工作。