本文由ImportNew-Leon Wang翻译自javacodegeeks。欢迎加入Java小组。转载请参见文章末尾的要求。

在这篇文章中,我们想要讨论一下Android应用开发中的一个重要组件——Android Service。与Activity不同,Service在Android中运行在后台,Service没有界面并且生命周期也与Activity不同。使用Service可以实现一些后台操作,例如从远程服务器上加载一个网页。我们可以使用Service在Android中实现多任务。

Android Service概述

我们知道,如果系统资源变得紧张,Android Activity可以被启动、停止、销毁甚至可能被重新创建。而Service被设计成拥有更长的生命周期。Service在Android中可以从Activity、广播接收器(Broadcast receiver)或者由其他Service中启动。

必须注意到的是,使用Service不会自动创建新的线程。所以,如果我们要在Service中实现一个简单的逻辑并且那不需要长时间处理,我们不必在一个单独的线程中运行它。但是,如果需要去实现一个复杂的逻辑并且会耗费长时间的处理,我们在创建新线程时必须小心,要不然由于Service运行在主线程可能引起ANR问题(应用程序无响应)。

在Android中Service主要使用的场景如下:

  • 实现多任务(multi-task)
  • 进程间通信(IPC)

第一种情况的典型例子是,应用需要从远程服务端下载数据。在这种情况下,可以使用与用户交互的Activity,并在用户使用应用时启动Service,在后台运行完成工作。还有一种场景,当Service完成了任务发送信息给用户。

在第二种情况下,我们想要“分享”一些通常的功能,这样不同的应用可以重用他们。例如,可以假设我们有一个可以发送邮件的Service,我们想要在几个应用分享这个服务,这样就不必重写新相同的代码。在这种情况下,我们可以使用IPC这样Service,暴露一个可以被其他应用调用的 “远程”接口。

Service基础

现在我们对Service有了更多的了解,我们来创建它。在Android中创建一个Service我们需要继承Service类。

1 2 3 4 5 6 7 8 public class TestService extends Service { @Override public IBinder onBind(Intent arg0) { return null ; } }

可以看到,我们只实现了一个叫做onBinde的方法。在上面的示例中,我们使用了本地服务,所以方法返回null。正如前面提到的,Service有它自己的生命周期,因此我们可以重写一些回调方法,这样就能处理其不同的状态了:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class TestService extends Service { @Override public void onCreate() { super .onCreate(); } @Override public void onDestroy() { super .onDestroy(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super .onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent arg0) { return null ; } }

第一个方法onCreate只有在Service被创建的时刻被调用。如果Service已经在运行中,这个方法将不会被调用。我们不能直接调用它,它是由系统负责调用的。

OnStartCommand方法是最重要的方法,因为它在我们需要启动Service的时候被调用。在这个方法中,我们拥有在运行Service时传递进来的Intent,这样就可以与Service交换一些信息。在这个方法中,我们实现自己的逻辑:如果不是耗时的操作可以直接在这个方法中执行,否则可以创建一个线程。正如你看到的那样,这个方法需要返回一个整型值。这个整型代表系统应该怎么样处理这个Service:

  • START_STICKY:使用这个返回值,如果系统杀死我们的Service将会重新创建。但是,发送给Service的Intent不会再投递。这样Service是一直运行的。
  • START_NOT_STICKY:如果系统杀死了Service,不会重新创建,除非客户端显式地调用了onStart命令。
  • START_REDELIVER_INTENT:功能与START_STICKY类似。另外,在这种情况下Intent会重新传递给Service。

OnDestory是在Service将被销毁时系统调用的方法。

一旦有了自定义的Service类,就要在Manifest.xml中声明,这样我们就可以使用了。

1 2 < service android:name = ".TestService" android:enabled = "true" />

启动和停止Service

正如我们知道的,一个Service会被启动、最后会被停止,这样就可以完成它的任务了。假设我们从一个Activity中启动它,可以使用Intent传递给Service一些信息。假设我们的Activity有两个按钮,一个来启动,一个来停止Service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 btnStart.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(MainActivity. this , TestService. class ); i.putExtra( "name" , "SurvivingwithAndroid" ); MainActivity. this .startService(i); } }); btnStop.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(MainActivity. this , TestService. class ); MainActivity. this .stopService(i); } });

在上面示例代码的第5行,我们创建一个传递类名的Intent来处理我们的服务,而且我们设置一些像名字这样的参数。然后在第7行的地方,我们启动这个Service。同样的方式,在17行我们停止了这个Service。

在开始按钮上点击,得到下面的Log:

可以注意到onCreate方法被调用了。因为这是我们第一次启动这个Service,如果我们在开始按钮上再次点击,系统不会调用onCreate方法。当我们在停止按钮上点击时,系统销毁这个Service。

IntentService

正如我们以前提到的,Service运行在主线程中。所以,我们在Service中实现逻辑时要非常小心。要考虑如果这个逻辑是一个阻塞操作,或者需要很长时间才能结束,可能会引发ANR问题。在这种情况下,我们要将逻辑移到独立的线程中。这就意味着,要在onStartCommand方法中创建一个线程,然后运行它。

从Service派生的另一个IntentService类可以简化我们的开发。当不需要在同一时间去处理多个请求时,这个类比较好用。这个类创建了一个工作线程来处理不同的请求。执行的操作如下:

  • 创建一个单独的线程来处理请求。
  • 创建一个请求队列并偶尔传递一个Intent。
  • 创建一个默认的onStartCommand实现。
  • 在所有的请求执行完毕后结束Service。

如果我们想要创建一个IntentService,需要继承IntentService类而不是Service类:

1 2 3 4 5 6 7 8 9 10 11 12 public class TestIntentService extends IntentService { public TestIntentService() { super ( "TestIntentService" ); } @Override protected void onHandleIntent(Intent intent) { } }

在这个实例中,我们只需要实现onHandleIntent方法。这里实现的外部逻辑不用关心操作是否耗时,因为这个方法在单独的线程中调用。

自动启动Service

很多时候我们想要自动启动我们的服务,例如在开机时自动启动。我们知道需要一个组件来启动Service。那么,怎么样做到自动启动呢?我们可以使用一个广播接收器来启动服务。例如,如果我们想要在智能手机开机时候启动它,可以先创建一个广播接收器监听这个事件(开机),然后启动Service。

1 2 3 4 5 6 7 8 9 public class BootBroadcast extends BroadcastReceiver { @Override public void onReceive(Context ctx, Intent intent) { ctx.startService( new Intent(ctx, TestService. class )); } }

在Manifest.xml中声明:

1 2 3 4 5 < receiver android:name = ".BootBroadcast" > < intent-filter > < action android:name = "android.intent.action.BOOT_COMPLETED" /> </ intent-filter > </ receiver >


原文链接: javacodegeeks 翻译: ImportNew.com - Leon Wang
译文链接: http://www.importnew.com/9019.html

更多相关文章

  1. android中如何捕获home键
  2. BlockCanary原理解析(Android端UI卡顿监测工具)
  3. 数据更新后让ListView自动滚动到底部
  4. Android(安卓)使用Intent传递对象
  5. Android(安卓)模拟器之 Market 安装
  6. 一句话_理解Activity四种启动模式
  7. android开发教程之listview使用方法
  8. 生命周期组件 Lifecycle 源码解析(一)
  9. Android(安卓)setTag方法定义key的问题

随机推荐

  1. 安装Android studio出现'tools.jar' seem
  2. 【转】Android 调试技术
  3. 编译android kernel遇到的问题
  4. Android http 网络框架对比
  5. Android application全局变量
  6. Aidl 练习
  7. Android(安卓)SDK Manager连不上Google服
  8. Android23-视图坐标系以及MotionEvent事
  9. android给Button或TextView等设置字体
  10. Android(安卓)环境建立