您的位置:首页 > 移动开发 > Android开发

Android4开发入门经典 之 第五部分:Service

2016-02-25 20:12 369 查看

Service基本概念

Service是什么

是一种能在后台运行,不需要用户界面,用来执行需要长时间处理的组件。

 

Service的说明

1:它通常由其他组件启动,并在后台持久的运行,即使用户已经切换到其他的应用,它仍然可以继续在后台运行。

2:其他组件能够跟service绑定,甚至能进行跨进程的通讯(IPC:interprocess communication)

3:一个service通常用来执行:网络传输、音乐播放、文件I/O、或者是与content provider进行交互等等。当然所有的操作过程都在background。

       


Service的两种形式

1:Started

如果是其他应用组件通过调用startService()方法启动的service,就被称为“Started” Service。

一旦启动了Service,它就会在后台运行,即使启动它的组件已经被销毁了,Service仍然会继续运行。一般这种启动Service的操作是不需要返回值的,当Service完成工作后,它自己会停止运行。

2:Bound

如果是其他应用组件通过调用bindService()方法绑定的service,就被称为“bound” Service。

绑定Service提供了Client和Server之间的交互,也就是允许组件和Service进行交互,发送请求,获得返回值等。甚至能够实现跨进程的通讯(IPC)。

绑定Service和绑定它的组件的运行周期是一样的,多个组件可以绑定到同一个Service,当所有绑定它的组件都销毁了的时候,Service也就销毁了。

nService和进程、线程

要注意一点:一个Service是运行在主线程和它的宿主进程中的,Service不会创建它自己的线程,也不会运行在单独的进程中。

因此,如果Service要执行特别耗费CPU的工作,或者是其他导致阻塞的工作,最好在Service里面创建新的线程来执行这些工作,这样能避免典型的ANR(Application Not Response)错误。

 Service和线程的使用建议

1:Service适用于在后台运行,不需要用户在界面上操作的功能。

2:Thread适用于你希望在应用之外执行一些功能,而且用户还需要操作界面,那么建议使用Thread;还有一种情况就是Service里面执行的工作特别耗费资源,容易引起主线程的阻塞,那么也建议使用线程。

 

Service基本的API-1

创建Service非常简单,写一个类继承Service,然后覆盖实现相应的回调方法即可,一些重要的回调方法如下:

1:onStartCommand():当其他组件启动Service的时候调用。当这个方法执行后,Service就启动起来在后台运行了。你可以调用stopSelf()或stopService()来停止Service。如果只是绑定服务,没有必要实现这个方法。

2:onBind():当其他组件绑定Service的时候调用。你必须提供一个接口给客户端,让它通过这个接口来和服务端通讯,通常会返回一个IBinder,你应该始终实现该方法,如果不用绑定的话,返回null。

3:onCreate():当Service第一次创建的时候由系统调用该方法。如果服务已经启动运行,将不会调用该方法。

4:onDestroy():当Service将要被销毁的时候调用该方法。你应该实现该方法来释放Service所使用的资源,比如:线程、注册的监听器、广播消息接受者等。

销毁Service

1:如果是通过其他组件调用startService()来创建的Service,需要调用stopSelf()或stopService()来停止Service

2:如果是绑定的Service,它会一直运行到所有绑定它的组件销毁后,由系统来销毁Service。

3:如果系统急需要资源,它会强行停止一些长时间运行,且运行级别较低的service,比如没有界面,在后台运行的某些service。

在manifest文件里面声明Service

要想使用Service,需要在manifest文件里面声明Service,

创建Started Service

通常有两个类可以选择:

1:service:这是所有Service的父类。当你直接继承这个类的时候,要注意在Service里面创建一个新的线程来执行工作,因为Service是运行在主线程里面的,否则容易引起主线程阻塞。

2:IntentService:这是Service的一个子类,它使用一个Worker Thread来处理请求,通常继承它是一个好的实现方式。你需要实现onHandleIntent()方法。

IntentService完成的工作

1:创建一个Worker Thread来处理请求,与Main Thread区别开来。

2:创建一个工作队列,每次传递一个intent到onHandleIntent()方法,你无需担心多线程的问题

3:当所有的请求都被处理后,自动停止Service。

4:提供onBind()方法的默认实现,返回null

5:提供onStartCommand()方法的默认实现,来把请求分发到onHandleIntent()方法

 

使用IntentService示例

public class MyService1 extends IntentService{
private int num = 0;
//需要这个构造方法来向父类传name值
public MyService1() {
super("MyService1");
}
protected void onHandleIntent(Intent in) {
//这里实现service的工作
Log.i("MyService1","onHandleIntent=="+num++);
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

继承Service示例

public class MyService extends Service{
public IBinder onBind(Intent arg0) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
//这里实现要处理的功能,这样实现会阻塞主线程,还应该在这里重新创建线程来执行功能
for(int i=0;i<10;i++){
Log.i("MyService","onStartCommand----------->"+startId+",i="+i);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return super.onStartCommand(intent, flags, startId);
}
}

创建Bound Service有三种方法:扩展Binder类、使用Messenger对象、使用AIDL(Android Interface Definition Language)

扩展Binder类来实现 Bound Service示例

public class MyService2 extends Service {
//定义给客户端使用的Binder
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
MyService2 getService() {
//返回当前实例给客户端,这样,客户端就可以操作服务的方法了
return MyService2.this;
}
}
public IBinder onBind(Intent intent) {
return mBinder;
}
//响应客户端的服务方法
public int getData() {
Log.i("MyService2","now get Data==");
return new Random().nextInt(100);
}
}

使用Bound Service的Activity示例

1:要实现一个绑定连接的回调实现

private MyService2 ms = null;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
//首先要强制造型
LocalBinder binder = (LocalBinder) service;
ms = binder.getService();
}
public void onServiceDisconnected(ComponentName arg0) { }
};

2:绑定Service
Intent in = new Intent();
in.setClass(HelloWorldActivity.this, MyService2.class);
HelloWorldActivity.this.bindService(in, mConnection,
HelloWorldActivity.this.BIND_AUTO_CREATE);

3:然后就可以调用Service提供的方法了

4:如果不想绑定这个服务了,可以使用unbindService方法

     


在Foreground运行Service

Foreground

某些时候,我们需要Service到前台来运行,这样它就能向用户提供很多用户关心的服务运行信息,而且不会被系统销毁掉。

在Foreground的Service必须在status bar提供notification,除非服务被停止或者服务重新回到后台运行。

startForeground 方法

要在Foreground运行service,只需要在Service中准备好相应的notification,方法和以前准备是一样的,只是最后调用的方法不是以前的mNotificationManager.notify方法,而是使用startForeground 方法

stopForeground 方法

要取消在Foreground运行service,可以调用stopForeground 方法

转自【http://blog.itpub.net/26715458/viewspace-717428/】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: