Android学习笔记---Service及IntentService理解
一.Android Service服务:
Android中的服务是运行在后台的服务,他是不可见的没有界面的东西。你可以启动一个服务Service来播放音乐,或者记录你地理信息位置的改变,或者启动一个服务来运行并一直监听某种动作。Service和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的请求或者动作。你可以在服务中开一一个线程,在线程中做耗时动作。
服务的生命周期图:
1.如何创建和开启一个服务:
第一步:创建一个类 ExampleService.java 继承android.app.Service
第二步:覆盖其中继承的方法 如下:
public class ExampleService extends Service { private static final String TAG = "Example"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.i(TAG, "ExampleService===>>onCreate"); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Log.i(TAG, "ExampleService===>>onStart"); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "ExampleService===>>onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "ExampleService===>>onDestroy"); super.onDestroy(); } }
第三步:启动服务:
Intent intent = new Intent(MainActivity.this, ExampleService.class); startService(intent);
第四步:关闭服务:
stopService(intent);//关闭服务
服务运行的生命周期顺序:
[onCreate()-->onStartCommand()--->onStart()-->运行服务--->调用stopService()--->onDestory()]
在Activity中通过startService()开启的服务,开启之后及时现在我们关闭Activity服务还一直在后台运行,只有调用stopService()才能关闭服务。
关闭Activity之后 我们在此点击按钮 重新开启服务。
注意:服务在后台运行我们再次点击startService()开启服务。将不会在调用 onCreate()服务。一个服务只会创建一次,销毁一次,但可以开始多次,因此,onCreate和onDestroy方法只会被调用一次,而onStart(或onStartCommand)方法会被调用多次。
如下图:
点击stopService()方法将关闭服务:
注意:onStart方法是在Android2.0之前的平台使用的.在2.0及其之后,则需重写onStartCommand方法,同时,旧的onStart方法则不会再被调用.
二.bindService()
Bound service 允许其它的组件(比如Activities)绑定到这个Service上,可以发送请求,也可以接受请求,甚至进行进程间的通话。Bound service 仅仅在服务于其它组件时存在,不能独自无限期的在后台运行。
调用者和服务绑在一起,调用者一旦退出服务也就终止[onCreate()-->onBind()-->onUnbind()-->onDestory()]
1.创建Bound Services
当创建一个能提供绑定功能的服务时,我们必须提供一个IBinder对象,客户端能使用这个对象与服务进行交互。在Android中有三种方式定义方式:
1.扩展Binder类
2.使用Messenger
3.使用AIDL (Android Interface Definition Language)
创建 步骤:
第一步:.创建一个类BinderService.java 继承 android.app.Service
public class BinderService extends Service { public class MyBinder extends Binder { public BinderService getBinderService() { return BinderService.this; } } private MyBinder binder=new MyBinder(); private static final String TAg = "BinderService"; @Override public IBinder onBind(Intent intent) { Log.i(TAg, "BinderService===>onBind()"); return binder; } public void UpFile() { Log.i(TAg, "BinderService===>UpFile()"); } @Override public void onCreate() { Log.i(TAg, "BinderService===>onCreate()"); super.onCreate(); } @Override public void onDestroy() { Log.i(TAg, "BinderService===>onDestroy()"); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { Log.i(TAg, "BinderService===>onUnbind()"); return super.onUnbind(intent); } }
第二步:在Service类中,创建一个Binder实例 包含客户端能调用的公共方法 返回当前服务对象
public class MyBinder extends Binder { public BinderService getBinderService() { return BinderService.this; } }
第三步:在onBind()方法中返回Binder实例
private MyBinder binder=new MyBinder(); private static final String TAg = "BinderService"; @Override public IBinder onBind(Intent intent) { return binder; }
第四步:在客户端,从onServiceConnected()方法中获得Binder实例。
private void bindService() { Intent intent=new Intent(MainActivity.this,BinderService.class); bindService(intent,conn,Context.BIND_AUTO_CREATE); } private void unBind() { if(isConnected) { unbindService(conn); } } private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { isConnected=false; } @Override//在onServiceConnected 中获取Binder的实例 public void onServiceConnected(ComponentName name, IBinder binder) { MyBinder myBinder=(MyBinder)binder; BinderService service=myBinder.getBinderService(); service.UpFile(); isConnected=true; } };
通过调用 bindService()开启服务 。
调用unBind()关闭服务,或者我们关闭Activity也会关闭服务
三.Android中Service运行在主线程中。
Android 中的服务是运行在主线程上的,通过下面的例子来说明Android服务运行的线程。如果是运行在主线程的,
那在服务中步要运行太耗时的操作。如果运行态耗时的操作将会是整个Activity处于假死状态,无在进行别的操作。如何要运行耗时操作
要用到多线程Thread 或者异步操作 InentService.
创建一个 MyServiceThread.java 继承 Service的服务:
public class MyServiceThread extends Service { private static final String TAG = "MyServiceThread"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.i(TAG, "MyServiceThread===>>onCreatre===>>线程ID:"+Thread.currentThread().getId()); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { try {
//这里进行耗时的操作 Log.i(TAG, "MyServiceThread===>>onStartCommand===>>线程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下载。。。。。"); Thread.sleep(5000); Log.i(TAG, "文件下载完成。"); } catch (InterruptedException e) { e.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.i(TAG, "MyServiceThread===>>onDestroy===>>线程ID:"+Thread.currentThread().getId()); super.onDestroy(); } }
程序为开启耗时服务时:
运行截图:下图可看出Android 中的Service确实是运行在主线程中。从运行前和运行后,当我们点击开启服务,按钮在服务没有运行
结束时,背景处于黄色,此时不能进行其他的操作。如果要运行耗时的操作需要应用多线程操作。
三.Android中Service多线程操作运行耗时操作。
一下演示Android服务如何在多线程下进行耗时操作。
1.创建ManyThreadService.java 服务
public class ManyThreadService extends Service { private static final String TAG = "ManyThreadService"; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { Log.i(TAG, "ManyThreadService==>>onCreate==>线程ID:"+Thread.currentThread().getId()); } private class MyThread extends Thread { @Override public void run() { try { Log.i(TAG, "ManyThreadService==>>文件下载线程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下载中。。。。。>>文件现在线程ID:"+Thread.currentThread().getId()); Thread.sleep(5000); Log.i(TAG, "文件现在完成。 >>文件下线线程ID:"+Thread.currentThread().getId()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "ManyThreadService==>>onStartCommand中开启线程==>线程ID"+Thread.currentThread().getId()); new MyThread().start(); return START_STICKY; } @Override public void onDestroy() { Log.i(TAG, "ManyThreadService==>>onDestory==>线程ID"+Thread.currentThread().getId()); super.onDestroy(); } }
2.创建新线程进行耗时操作:
private class MyThread extends Thread { @Override public void run() { try { Log.i(TAG, "ManyThreadService==>>文件下载线程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下载中。。。。。>>文件现在线程ID:"+Thread.currentThread().getId()); Thread.sleep(5000); Log.i(TAG, "文件现在完成。 >>文件下线线程ID:"+Thread.currentThread().getId()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3.开启新线程:
public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "ManyThreadService==>>onStartCommand中开启线程==>线程ID"+Thread.currentThread().getId()); new MyThread().start(); return START_STICKY; }
运行效果:从下图看出出,多线程并行操作,提高执行的效率。如果要在Android服务中执行耗时的并行操作服务,适应多线程操作时不错的选择。
如果只是运行异步请求操作 IntentService是不错的选择。
三.Android中IntentSevice操作。
IntentService是Service类的子类,用来处理异步请求。客户端通过startService(Intent)方法传递请求给IntentService,
IntentService通过worker thread处理每个Intent对象,执行完所有工作后自动停止Service。
写构造方法 复写onHandleIntent()方法
IntentService执行如下操作
1.创建一个与应用程序主线程分开worker thread用来处理所有通过传递过来的Intent请求
2.创建一个work queue,一次只传递一个intent到onHandleIntent()方法中,从而不用担心多线程带来的问题
3.当处理完所有请求后自动停止服务,而不需要我们自己调用stopSelf()方法
4.默认实现了onBind()方法,返回值为null
5. 默认实现了onStartCommand()方法,这个方法将会把我们的intent放到work queue中,然后在onHandleIntent()中执行。
创建 MyIntentService.java 继承:android.app.IntentService
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; public MyIntentService() { super("MyIntentService"); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.i(TAG, "MyIntentService==>>onCreate==>>线程ID:"+Thread.currentThread().getId()); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "MyIntentService==>>onStartCommand==>>线程ID:"+Thread.currentThread().getId()); return super.onStartCommand(intent, flags, startId); } @Override protected void onHandleIntent(Intent intent) { try { Log.i(TAG, "MyIntentService==>>onHandleIntent==>>线程ID:"+Thread.currentThread().getId()); Log.i(TAG, "文件下载中。。。。。>>文件下载线程ID:"+Thread.currentThread().getId()); Thread.sleep(5000); Log.i(TAG, "文件现在完成>>文件下载线程ID:"+Thread.currentThread().getId()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onDestroy() { Log.i(TAG, "MyIntentService==>>onDestory==>>线程ID:"+Thread.currentThread().getId()); super.onDestroy(); } }
运行效果:从下图可以看出,在每次开启服务时传过去的inent,耗时操作都是有一个线程来执行处理。而所有操作排列成一个线程队列,先执行完个操作,紧接着
执行下一个操作。执行完所以操作后 服务会自动onDestory操作进行销毁。
本写的这里,有些问题是我通过实验总结出来的,有错误的地方请指出来。错误的地方希望大家指出。谢谢。