转载

Android服务(Service)研究

Service是android四大组件之一,没有用户界面,一直在后台运行。

为什么使用Service启动新线程执行耗时任务,而不直接在Activity中启动一个子线程处理?

1、Activity会被用户退出,Activity所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存可能会优先终止该进程;

2、如果宿主进程被终止,那么该进程内所有的子线程也会被终止,这样可能导致子线程无法执行完成;

3、其实两种方式都是可以处理耗时任务的,使用场景不同而已。

一、通过Start方式启动Service

这种方式启动的Sevice,访问者与service之间没有关联,即使访问者退出Service仍然执行

生命周期:onCreate()->onStartCommand()-> onDestroy()

》定义一个继承Service的子类

public class NormalService extends Service {  @Override  public IBinder onBind(Intent arg0) {   return null;  }  @Override  public int onStartCommand(Intent intent, int flags, int startId) {   Toast.makeText(this, "启动成功", Toast.LENGTH_SHORT).show();   Log.d("NormalService", "启动成功");   //一般在这里启动新线程执行耗时的操作   return super.onStartCommand(intent, flags, startId);  } } 

》在AndroidManifest.xml文件中配置该Service

<service android:name="com.android.servicetest.service.NormalService" />

》在activity中使用

private void startNormal() {     nomalIntent = new Intent();     nomalIntent.setClass(this, NormalService.class);     startService(nomalIntent); }

二、通过bind方式启动Service

这种方式启动的Sercice,访问者与Service绑定在一起,访问者退出,Service也就终止了

生命周期:onCreate()->onBind()->onUnbind()->onDestroy()

》定义一个继承Service的子类

public class BinderService extends Service {  private int count;  private MyBinder mBinder;  @Override  public IBinder onBind(Intent arg0) {   if (mBinder == null) {    mBinder = new MyBinder();   }   Toast.makeText(this, "绑定成功", Toast.LENGTH_SHORT).show();   Log.d("BinderService", "绑定成功");   return mBinder;  }  @Override  public void onCreate() {   super.onCreate();   new Thread(new Runnable() {    @Override    public void run() {    while (true) {     try {     Thread.sleep(1000);     count++;     } catch (Exception e) {     }    }    }   }).start();  }  public class MyBinder extends Binder {   public int getCount() {    return count;   }  } } 

》在AndroidManifest.xml文件中配置该Service

<service android:name="com.android.servicetest.service.BinderService" />

》在activity中使用

private MyBinder mBinder; private ServiceConnection conn = new ServiceConnection() {  @Override  public void onServiceDisconnected(ComponentName arg0) {  }  @Override  public void onServiceConnected(ComponentName arg0, IBinder binder) {  mBinder = (BinderService.MyBinder) binder;  } }; private void bindService() {  bindIntent = new Intent();  bindIntent.setClass(this, BinderService.class);  bindService(bindIntent, conn, Service.BIND_AUTO_CREATE); } 
@Override protected void onDestroy() {     super.onDestroy();     unbindService(conn); }

Binder对象相当于Service组件的内部钩子,关联到绑定的Service组件;

当其他的程序组件绑定该Service时,Service会把Binder对象返回给其他程序组件,其他程序组件通过该Binder对象即可与Service组件进行实时通信。

三、IntentService,处理异步请求的服务

IntentService是Service的子类,它增加了额外的功能:

使用队列来管理请求Intent,每当客户端代码通过Intent请求启动IntentService时,IntentService会将该Intent加入队列中,然后开启一条新的worker线程处理队列中的Intent,因此不会阻塞主线程。

IntentService会按次序处理队列中的Intent,该线程保证同一时刻只处理一个Intent。

》IntentService的实现

public class IntentServiceTest extends IntentService{  public IntentServiceTest() {   super("IntentService");  }  @Override  protected void onHandleIntent(Intent arg0) {   Toast.makeText(this, "启动成功", Toast.LENGTH_SHORT).show();   Log.d("IntentServiceTest", "启动成功");   //该方法可以执行耗时的操作   long endTime = System.currentTimeMillis() + 20 * 1000;   while(System.currentTimeMillis() < endTime){    synchronized (this) {    try{     wait(endTime - System.currentTimeMillis());    }catch(Exception e){    }    }   }  } }

》在AndroidManifest.xml文件中配置该Service

<service android:name="com.android.servicetest.service.IntentServiceTest" />

》在activity中使用

private void startIntentService(){     serviceIntent = new Intent();     serviceIntent.setClass(this, IntentServiceTest.class);     startService(serviceIntent); }

四、跨进程调用Service(AIDL Service)

Android各应用程序都运行在自己的进程中,进程之间无法直接进行数据交换,为了事项这种跨进程通信,Android提供了AIDL Service。

》创建AIDL文件,定义接口的源代码必须以.aidl结尾

package com.android.servicetest.service;  interface IMusic{     String getName();     String getYear(); }

定义好AIDL接口之后,ADT工具会自动在gen/ com/android/servicetest/service/目录生成一个IMusic接口;

在该接口里包含一个Stub内部类,该内部类除了实现IMusic接口还实现了IBinder接口,这个Stub类将会作为远程Service的回调类。

》定义一个Service实现类

public class MusicService extends Service{  private MusicBinder mBinder;  @Override  public IBinder onBind(Intent arg0) {   if(mBinder == null){    mBinder = new MusicBinder();   }   Toast.makeText(this, "绑定成功", Toast.LENGTH_SHORT).show();   Log.d("MusicService", "绑定成功");   return mBinder;  }  public class MusicBinder extends IMusic.Stub{   @Override   public String getName() throws RemoteException {    return "本草纲目";   }   @Override   public String getYear() throws RemoteException {    return "2006";   }  } } 

》在AndroidManifest.xml文件中配置该Service

<service android:name="com.android.servicetest.service.MusicService" />

》在activity中使用

private IMusic musicService; private ServiceConnection = new ServiceConnection() {  @Override  public void onServiceDisconnected(ComponentName arg0) {  }  @Override  public void onServiceConnected(ComponentName arg0, IBinder binder) {   //获取远程Service的OnBind方法返回的对象的代理   musicService = IMusic.Stub.asInterface(binder);  } }; private void bindAidlService(){  aidlIntent = new Intent();  aidlIntent.setClass(this, MusicService.class);  bindService(aidlIntent, connAidl, Service.BIND_AUTO_CREATE); } private void showContent() {  String content = "";  try {   content = musicService.getYear() + musicService.getName();  } catch (Exception e) {  }  Toast.makeText(this, content, Toast.LENGTH_SHORT).show(); }  
@Override protected void onDestroy() {     super.onDestroy();     unbindService(connAidl); }

这种方式和绑定本地Service的差别很小,只是获取Service回调的方式有区别:

绑定本地Service时可以直接获取OnBind方法的返回值;绑定远程Service时获取的事OnBind方法返回的对象的代理。

正文到此结束
Loading...