博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Service的理解
阅读量:5129 次
发布时间:2019-06-13

本文共 9666 字,大约阅读时间需要 32 分钟。

转自

 

Service的理解

Service是什么?

Service是一种可以在后台运行相关任务的组件。没有界面。其存在的线程是主线程,一般会通过启动子线程来执行耗时操作。
Service有什么用?
可用于在后台执行下载任务。从而不影响用户界面操作。
Service分启动型服务、绑定型服务两种。
绑定服务中的创建Binder的扩展类的目的是什么?
该类主要用于获取Service的实例,以及执行相关的方法。
额外知识
1.不绑定服务,直接点击取消绑定服务会报错。因此需要通过判断Binder对象是否为空来处理。
2.服务可以不定义Action,通过Intent指定要跳转的Service即可。
3.Service的有效范围是所有满足条件的Activity。
4.在Service里执行耗时操作会导致ANR,启动新的线程执行耗时操作可有效避免。

两种服务的区别

Service类型 说明 使用步骤
启动型服务 1.生命周期为onCreate->onStartCommand->onDestroy 
2.服务一旦启动后,需要调用stopService方法或stopSelf方法才能停止。 
3.可常驻系统。
1.通过调用startService启动服务 
2.通过stopService停止服务
绑定型服务 1.生命周期为onCreate->onBind->onUnbind->onDestory 
2.需要返回Binder对象,即定义Binder的子类。
3.通过Binder子类的方法来获取Service对象,用于与Activity交互。 
4.在Activity中需要通过创建ServiceConnection对象来获取service实例。从而调用service里的方法。
1.通过bindService绑定服务 
2.通过unbindService取消绑定服务

Service生命周期

Service的类型及其示例

启动型服务 - StartService

使用

1.创建java类继承Service
2.重写onStart、onCreate等方法。
3.在onCreate中新开子线程,用于执行任务。

示例 - 启动型服务

Service作用

打印0-2000的数字,完毕后停止服务

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
public class CalcService extends Service {
private int total; private boolean openService; //结束服务时的标识 public CalcService() {
} @Override public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() {
super.onCreate(); LogTool.e("CalcService", "onCreate"); } @Override public int onStartCommand(final Intent intent, int flags, final int startId) {
LogTool.e("CalcService", "onStartCommand"); Functions.toast("Service已启动,请查看LOG"); //启动线程执行耗时操作。通常是下载之类的任务 new Thread(new Runnable() {
@Override public void run() {
while (!openService) {
try {
Thread.sleep(100); } catch (InterruptedException e) {
e.printStackTrace(); } LogTool.e("CalcService", total); total++; builder.setSubText("total:" + total); if (total == 2000) {
stopSelf(); } } } }).start(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() {
super.onDestroy(); LogTool.e("CalcService", "onDestroy"); Functions.toast("CalcService已停止,请查看LOG"); openService = true; } }
1 2 3 4 5
// Activity中的代码 public void startService(View v){
Intent intent = new Intent(this,CalcService.class); startService(intent); }

绑定型服务 - BindService

BindService(Intent,ServiceConnection,Context.BIND_AUTO_CREATE)

参数分别为Intent,ServiceConnection,标识号。通常为BIND_AUTO_CREATE。
使用
1.创建java类继承Service
2.创建Java类继承Binder类。用于返回Service实例。
3.重写onBind、onUnBind等方法。
4.在Activity中创建ServiceConnection对象,并获取Binder实例。
ps:为防止未绑定服务,用户点击取消绑定而导致的崩溃。需要对unbindService进行边缘性处理。

示例 - 普通绑定型服务

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
public class BindService extends Service {
private BindService service; private TestBinder binder = new TestBinder(); private int count = 0; public class TestBinder extends Binder {
//通过Binder对象来获取服务对象,从而调用服务里的方法 public BindService getService() {
if (service == null) {
service = new BindService(); } return service; } } private boolean closeThread; public BindService() {
} @Override public void onCreate() {
super.onCreate(); new Thread(new Runnable() {
@Override public void run() {
while (!closeThread) {
LogTool.e("BindService", "count:" + count); count++; } } }).start(); } @Override public TestBinder onBind(Intent intent) {
LogTool.e("BindService", "onBind"); return binder; } @Override public void onDestroy() {
super.onDestroy(); this.closeThread = true; LogTool.e("BindService", "onDestroy"); Functions.toast("BindService已停止"); } @Override public boolean onUnbind(Intent intent) {
LogTool.e("BindService", "onUnbind"); return true; } public void startDownload() {
Functions.toast("开始执行耗时任务,点击UnbindService按钮或返回按钮可取消任务"); } }

Activity中的代码

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
private ServiceConnection connection = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName name, IBinder service) {
binder = (BindService.TestBinder) service; binder.getService().startDownload(); } @Override public void onServiceDisconnected(ComponentName name) {
Functions.toast("断开连接"); LogTool.e("BindService", "serviceDisconnected"); } }; //启动服务 public void BindService(View v) {
Intent intent = new Intent(this, BindService.class); bindService(intent, connection, Service.BIND_AUTO_CREATE); } // 取消绑定服务,边缘性处理 public void UnbindService(View v) {
if (binder != null) {
unbindService(connection); } }

示例 - 绑定型远程服务

理解

如何定义远程服务?
在配置文件中添加代码android:progress=”:remote”即可
为什么设置了Service为远程Service就不会导致ANR了?
远程服务是指将服务放到另一个进程中执行,所以就不会导致程序的ANR现象。
如何跨进程与Activity进行通信? 见示例
如何实现跨程序通信?

示例 - 实现跨进程与Activity交互

步骤

1.创建aidl文件,定义接口(TestInterface)及相关方法。点击make project,自动生成Stub相关的接口。
2.创建Service类,并在ManiFest文件设置远程属性。android:process=”:remote”
3.在Service中创建接口TestInterface.Stub 对象,重写接口方法。
4.在Activity中通过AIDL接口的asInterface方法来获取AIDL对象。
5.利用接口对象调用相关方法。

1 2 3 4 5
// 创建aidl文件,定义接口。 package io.tanjundang.study.test.service; interface RemoteAidlInterface {
void calcMsg(); }
1 2 3 4
// 配置服务远程属性 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Service中创建远程接口的Stub对象 public class RemoteService extends Service {
RemoteAidlInterface.Stub mBinder = new RemoteAidlInterface.Stub() {
@Override public void calcMsg() throws RemoteException {
LogTool.e("RemoteService", "66666"); } }; @Override public Binder onBind(Intent intent) {
return mBinder; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
// Activity中调用远程接口的方法 public class RemoteActivity extends AppCompatActivity {
private RemoteAidlInterface mBinder; private ServiceConnection connection = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBinder = RemoteAidlInterface.Stub.asInterface(iBinder); try {
mBinder.calcMsg(); } catch (RemoteException e) {
e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) {
} }; @Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_remote); } public void StartRemoteService(View v) {
Intent intent = new Intent(this, RemoteService.class); bindService(intent, connection, BIND_AUTO_CREATE); } public void UnbindRemoteService(View v) {
if (mBinder != null) {
unbindService(connection); } } }

示例 - 实现跨程序与Activity交互

步骤

实现步骤跟上面类似。只是需要为Service定义Action,以及将AIDL接口及其包名复制到另一程序中。即可实现跨程序交互。

IntentService

理解

为什么有这个类?
该类是Service的子类,主要是简化了异步操作繁琐复杂的代码。
有什么特点?
1.不需要自己创建子线程。
2.不需要考虑何时关闭服务。
使用情景是什么?
多次调用startService。
使用
1.Service继承IntentService。
2.以类名为参数调用父类构造方法。
3.重写onHandleIntent核心方法以及其他方法。

前台服务

什么是前台服务?

普通服务在内存不足的情况下会被系统杀掉,而前台服务不会因为内存不足而被杀掉。
前台服务有什么特点?
前台服务有通知栏提示,可设定相关的标题、提示灯。例如天气、播放器等。
前台服务的使用
1.构建Notification对象。
2.通过startForeground方法启动通知栏。
3.通过stopForeground方法关闭通知栏。
注意
Notification的构建中,若不调用setSmallIcon方法设置Icon,其他相关设置(标题、提示)均无效。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
@Override    public int onStartCommand(final Intent intent, int flags, final int startId) {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()); builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(getApplicationContext(), MainActivity.class), 0)); builder.setContentTitle("前台服务"); //不知道什么鬼,不设置Icon,其他信息都不显示 builder.setSmallIcon(R.drawable.ic_menu_camera); builder.setContentText("二级子标题"); builder.setSubText("三级子标题"); Notification notification = builder.build(); //开启通知栏提示 startForeground(startId, notification); LogTool.e("CalcService", "onStartCommand"); Functions.toast("Service已启动,请查看LOG"); total = intent.getIntExtra("msg", 100); return super.onStartCommand(intent, flags, startId); }

 

转载于:https://www.cnblogs.com/wxmdevelop/p/7248779.html

你可能感兴趣的文章
Radon变换——MATLAB
查看>>
第五章笔记
查看>>
Iroha and a Grid AtCoder - 1974(思维水题)
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
[LeetCode] Palindrome Number
查看>>
我对于脚本程序的理解——百度轻应用有感
查看>>
SQL更新某列包含XX的所有值
查看>>
网易味央第二座猪场落户江西 面积超过3300亩
查看>>
面试时被问到的问题
查看>>
spring 事务管理
查看>>
VS2008 去掉msvcr90的依赖
查看>>
当前记录已被另一个用户锁定
查看>>
Bootstrap
查看>>
Node.js 连接 MySQL
查看>>
ACM-ICPC 2018 world final A题 Catch the Plane
查看>>
那些年,那些书
查看>>
面向对象六大基本原则的理解
查看>>