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

01.1android Service的概念及作用

2016-03-05 08:52 543 查看
1、概念及作用

由于ANR对Activity和BroadcastReceiver响应时间的限制(Activity对事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不适合执行较耗时操作,这样像网络、数据库、复杂计算这类耗时操作的执行就需要一个组件来承担。Service作为Android四大组件之一,其功能之一就是耗时操作的执行,主要功能如下:

a. 执行需要长时间运行的操作,这个操作不与用户进行交互,如网络下载、大文件I/O、复杂计算。

b. 应用内或应用间数据通信,Android每个应用程序都在自己的dalvik虚拟机中运行,一个应用是不允许访问其他应用的内存信息的,为此Android引入了Content Provider在不同应用间共享数据,BroadcastReceiver广播信息给不同应用程序,但Content Provider更多用于数据的共享,BroadcastReceiver广播的信息会被所有应用接收较耗费系统资源,对于两个应用间动态的进行交互还需要通过Service来完成。

startService启动不可进行交互的Service

bindService启动的Service应用内交互

2、使用

(1) startService启动不可进行交互的Service

a. 示例代码及介绍

Service示例

public class MyService extends Service {

@Override

public void onCreate() {

super.onCreate();

Toast.makeText(this, "Service Create", Toast.LENGTH_SHORT).show();

}

@Override

public void onDestroy() {

Toast.makeText(this, "Service Destroty", Toast.LENGTH_SHORT).show();

super.onDestroy();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Toast.makeText(this, "Service Start", Toast.LENGTH_SHORT).show();

return super.onStartCommand(intent, flags, startId);

}

@Override

public IBinder onBind(Intent intent) {

return null;

}

}

务都必须在AndroidManifest.xml文件中注册<service android:name=".MyService"/>,在Activity中定义对象private Intent myServiceIntent = new Intent(this,
MyService.class);在onCreate函数中startService(myServiceIntent)启动服务; onDestroy函数中stopService(myServiceIntent)关闭服务;

b. 生命周期

通过startService启动服务,若服务未启动,会先执行onCreate函数(若服务已启动则不执行此函数),再执行onStartCommand函数。由此可知多次调用startService传入相同参数不会启动多个服务(onStartCommand函数会执行多次),所以最终只需要调用一次stopService或stopSelf函数停止服务;我们可以将service的处理逻辑放入onStartCommand函数中。服务一直运行,在程序退出后服务也不会停止,直到stopService或stopSelf函数被调用,当然可能被系统回收。

对于onStartCommand的返回值,若返回START_STICKY表示服务通过显式调用启动或停止,若返回START_NOT_STICKY orSTART_REDELIVER_INTENT表示服务仅在有请求发送过来处理时才处于运行状态

c. 使用场景

因为这种方式Service无法与外部进行方便的动态交互,所以适合做后台服务,如网络下载(用户通过Intent传入Url到Service)

(2) bindService启动的Service应用内交互

a. 示例代码及介绍

在上面的方式中Context可以通过Intent向Service传入简单的信息,但是如果希望调用Service的接口进行操作或是获取Service的属性则无法实现,这里我们可以通过bindService实现,如下先定义自己的服务

自定义Service

public class MyService extends Service {

private int count;
private MyBinder myBinder = new MyBinder();

@Override
public void onCreate() {
Toast.makeText(this, "Service onCreate", Toast.LENGTH_SHORT).show();
count = 0;
super.onCreate();
}

@Override
public void onDestroy() {
Toast.makeText(this, "Service onDestroy", Toast.LENGTH_SHORT).show();
super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}

/**
* 服务被绑定时调用
* 返回值用于让调用者和服务通信,传入ServiceConnection的public void onServiceConnected(ComponentName name, IBinder service)函数第二个参数
*/
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}

public int getCount() {
return count;
}

public int increaseCount() {
return ++count;
}

public int decreaseCount() {
return --count;
}

public class MyBinder extends Binder {

MyService getService() {
return MyService.this;
}
}
}

从上可以看出我们重写onBind函数并返回自己的Binder用于调用者和服务之间通信。下面我们在调用者中进行调用

定义自己的Service、Intent、ServiceConnection对象

private MyService myService;

private Intent myServiceIntent;

private ServiceConnection con = new ServiceConnection() {

/**

* 服务所在进程被kill或是crash时系统调用,而不是unbindService时调用

*/

@Override

public void onServiceDisconnected(ComponentName name) {

Toast.makeText(getApplicationContext(), "Service disconnect",

Toast.LENGTH_SHORT).show();

}

/**

* 服务连接时调用,若已经连接不进行调用

*/

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

myService = ((MyBinder)service).getService();

Toast.makeText(getApplicationContext(), "Service Connect", Toast.LENGTH_SHORT).show();

}

};

接着调用bindService(myServiceIntent, con, Context.BIND_AUTO_CREATE);

绑定服务,绑定成功返回true。

这时会执行ServiceConnection对象的onServiceConnected函数为myService变量赋值。接着我们就可以通过myService.increaseCount();操作Service的属性,myService.getCount()获得Service的属性,这样我们就成功和Service进行了通信。在不需要通信时通过unbindService(con);解除服务绑定。

b. 生命周期

通过bindService绑定服务,若服务未启动,会先执行Service的onCreate函数,再执行onBind函数,最后执行ServiceConnection对象的onServiceConnected函数。若服务已启动但尚未绑定,先执行onBind函数,再执行ServiceConnection对象的onServiceConnected函数。若服务已绑定成功,则直接返回。这里不会自动调用onStartCommand函数。

通过unbindService解除绑定服务,若已绑定成功,会先执行Service的onUnbind函数,再执行onDestroy函数,注意这里不会执行ServiceConnection对象的onServiceDisconnected函数,因为该函数是在服务所在进程被kill或是crash时被调用。若服务尚未绑定系统会报服务尚未注册异常,我们可以通过如下代码解决

if (myService != null) {

unbindService(con);

myService = null;

}

(2) bindService启动的Service应用内交互

a. 示例代码及介绍

在上面的方式中Context可以通过Intent向Service传入简单的信息,但是如果希望调用Service的接口进行操作或是获取Service的属性则无法实现,这里我们可以通过bindService实现,如下先定义自己的服务

自定义Service

public class MyService extends Service {

private int count;
private MyBinder myBinder = new MyBinder();

@Override
public void onCreate() {
Toast.makeText(this, "Service onCreate", Toast.LENGTH_SHORT).show();
count = 0;
super.onCreate();
}

@Override
public void onDestroy() {
Toast.makeText(this, "Service onDestroy", Toast.LENGTH_SHORT).show();
super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}

/**
* 服务被绑定时调用
* 返回值用于让调用者和服务通信,传入ServiceConnection的public void onServiceConnected(ComponentName name, IBinder service)函数第二个参数
*/
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}

public int getCount() {
return count;
}

public int increaseCount() {
return ++count;
}

public int decreaseCount() {
return --count;
}

public class MyBinder extends Binder {

MyService getService() {
return MyService.this;
}
}
}

从上可以看出我们重写onBind函数并返回自己的Binder用于调用者和服务之间通信。下面我们在调用者中进行调用

定义自己的Service、Intent、ServiceConnection对象

private MyService myService;
private Intent myServiceIntent;
private ServiceConnection con = new ServiceConnection() {

/**
* 服务所在进程被kill或是crash时系统调用,而不是unbindService时调用
*/
@Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(getApplicationContext(), "Service disconnect",
Toast.LENGTH_SHORT).show();
}

/**
* 服务连接时调用,若已经连接不进行调用
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myService = ((MyBinder)service).getService();
Toast.makeText(getApplicationContext(), "Service Connect", Toast.LENGTH_SHORT).show();
}
};

接着调用bindService(myServiceIntent, con, Context.BIND_AUTO_CREATE);
绑定服务,绑定成功返回true。
这时会执行ServiceConnection对象的onServiceConnected函数为myService变量赋值。接着我们就可以通过myService.increaseCount();操作Service的属性,myService.getCount()获得Service的属性,这样我们就成功和Service进行了通信。在不需要通信时通过unbindService(con);解除服务绑定。

b. 生命周期
通过bindService绑定服务,若服务未启动,会先执行Service的onCreate函数,再执行onBind函数,最后执行ServiceConnection对象的onServiceConnected函数。若服务已启动但尚未绑定,先执行onBind函数,再执行ServiceConnection对象的onServiceConnected函数。若服务已绑定成功,则直接返回。这里不会自动调用onStartCommand函数。

通过unbindService解除绑定服务,若已绑定成功,会先执行Service的onUnbind函数,再执行onDestroy函数,注意这里不会执行ServiceConnection对象的onServiceDisconnected函数,因为该函数是在服务所在进程被kill或是crash时被调用。若服务尚未绑定系统会报服务尚未注册异常,我们可以通过如下代码解决

if (myService != null) {
unbindService(con);
myService = null;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: