Service是android四大组件之一,没有用户界面,一直在后台运行。
1、Activity会被用户退出,Activity所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存可能会优先终止该进程;
2、如果宿主进程被终止,那么该进程内所有的子线程也会被终止,这样可能导致子线程无法执行完成;
3、其实两种方式都是可以处理耗时任务的,使用场景不同而已。
这种方式启动的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); }
这种方式启动的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是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); }
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方法返回的对象的代理。