Android四大组件之Service服务学习笔记(一)
2016-08-31 20:03
746 查看
Android四大组件之Service服务学习笔记(一)
Service是安卓四大组件之一,服务是用在后台处理事情的,并且是不可见的,该服务不是我们所说的服务器的服务,他经常用来处理一些循环操作,但是它不同于子线程,服务是运行在主线程中的。服务一般分为本地服务和远程服务,这里先介绍本地服务。
本地服务通常用两种启动方式
1. 直接启动模式
我们可以通过startService(Intent intent)方式去直接启动一个服务,对于intent意图,我们也可以用两种形式
创建,一种是显示启动,一种是隐示启动,但是需要注意的是,在android5.0以后,所有的服务尽量通过显示
意图来启动。否则就直接程序崩溃。所以建议都使用显示方式启动服务。如果一定要使用隐示启动方式, 则在对应的intent中添加一句
intent.setPackage(对应服务所在的包名),通过这个方法,可以防止5.0后隐示启动发生崩溃的作用。下面通过代码来详细讲解下。
MainActivity.java
public class MainActivity extends AppCompatActivity { private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onClick(View view){ intent = new Intent(this,MyService.class); //intent.setPackage("cn.itrealman.servicedemo");5.0以后需要加上这句代码 switch (view.getId()) { case R.id.start: //启动服务 startService(intent); break; case R.id.stop: //停止服务 stopService(intent); break; } } }
在AndroidManifest.xml中配置Service
<service android:name=".MyService" android:enabled="true" android:exported="true"> <!--<intent-filter>--> <!--建议不用写,因为5.0后的系统不支持隐示启动--> <!--<action android:name="test.service" />--> <!--</intent-filter>--> </service>
MyService.java
public class MyService extends Service { public MyService() { Log.d("IT_Real", "MyService: 构造方法"); } /** * 这个方法是通过绑定的方式才会调用该方法 * @param intent * @return */ @Override public IBinder onBind(Intent intent) { Log.d("IT_Real", "onBind: "); return null; } /** * 服务启动后初始化内部数据的方法,只会在第一次启动该服务的时候调用一次 */ @Override public void onCreate() { Log.d("IT_Real", "onCreate: "); super.onCreate(); } /** * 销毁服务 */ @Override public void onDestroy() { Log.d("IT_Real", "onDestroy: "); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { Log.d("IT_Real", "onUnbind: "); return super.onUnbind(intent); } /** * 这个方法是直接启动服务时调用的方法,不过该方法已经过时了 * 被下面的onStartCommand方法代替了 * @param intent * @param startId */ @Override public void onStart(Intent intent, int startId) { Log.d("IT_Real", "onStart: "); super.onStart(intent, startId); } /** * 这个方法也是直接启动服务时调用的方法 * @param intent * @param flags * @param startId * @return */ @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("IT_Real", "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } }
在上面的代码中,当我们点击启动按钮时,相应的服务被启动,在此之前,我们先看一下直接启动方式服务的生命周期图:
在上面的图中,我可以了解到,当我们第一次启动服务时,会先调用onCreate()——>onStartCommand()——onStart(),然后服务会开始运行,直到调用stopService()方法才会停止服务,然后会调用相应的onDestory()方法,如果服务已经启动,我们多次点击启动服务按钮,则会多次掉用onStartCommand()——>onStart()方法
对于上面的这种方式,我们不会获取任何服务对象,也不能操作任何服务里面的数据,都是系统自己去操作的,加入说,我们的服务里面有一个doSth()方法,我想去调用这个方法做该事情,那么该怎么调用呢?这个时候,我们就只能去通过在onStartCommand()方法里面去调用了(在onStart()方法中也可以调用,但是不推荐这样使用,过时的方法我能不用就不用),代码如下:
/** * 这个方法也是直接启动服务时调用的方法 * @param intent * @param flags * @param startId * @return */ @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("IT_Real", "onStartCommand: "); //通过调用该方法 doSth(); return super.onStartCommand(intent, flags, startId); } private void doSth(){ Log.d("IT_Real", "doSth: 我正在做某事..."); }
这样我们就能完成需要操作的事情了,但是这样的操作往往会很不方便,不能很好的让用户去通过某种方式去操作,比如在播放音乐的时候,我们就会很难去控制服务去处理某些事情,所以一般我们会通过绑定的方式来启动服务。
2. 绑定启动模式
对于绑定启动服务,我们可以很好的获取到服务给我们返回的Ibinder对象,由于Ibinder是一个接口,通常我们会返回一个Ibinder的子类Binder对象。一般情况下,我们会去继承Binder对象,添加自己所需要的实现功能。绑定启动的方式是通过bindService(Intent intent, ServiceConnection conn, int flags)绑定服务,该方法的三个参数如下:
intent:通过Intent指定要启动的服务
conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与service之间的连接情况。当访问者与Service直接连接成功时将回调ServiceConnection对象的onServiceConnected(ComponentName name, IBinder service)方法,当Service所在的宿主进程由于异常中断或者其他原因终止,导致该Service与访问者之间断开连接时,会调用ServiceConnection对象的onServiceDisconnected(ComponentName name)方法。
flags:指定绑定时,是否通过自动创建Service(未创建的情况下),如果该参数指定0(不创建),或者写BIND_AUTO_CREATE(自动创建)
创建代码如下:
MainActivity.java
public class MainActivity extends AppCompatActivity { private Intent intent; private MyServiceConnection conn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new MyServiceConnection(); } public void onClick(View view){ intent = new Intent(this,MyService.class); switch (view.getId()) { case R.id.bindStart: bindService(intent,conn,BIND_AUTO_CREATE); break; case R.id.bindStop: unbindService(conn); break; } } /** * ServiceConnection类,通过该类中的onServiceConnected方法 * 中的IBinder service对象可以获取到绑定的服务对象中的MyBinder对象 * 然后可以通过MyBinder对象中的getBindService方法获取我们的 * MyBindService对象 */ class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取Binder对象 MyBindService.MyBinder service1 = (MyBindService.MyBinder) service; MyBindService service2 = service1.getBindService(); } @Override public void onServiceDisconnected(ComponentName name) { } } }
在AndroidManifest.xml中配置Service
<service android:name=".MyBindService" android:enabled="true" android:exported="true"> </service>
MyBindService.java
public class MyBindService extends Service { public MyBindService() { } /** * 返回的IBinder对象 */ class MyBinder extends Binder{ public MyBindService getBindService(){ returnMyBindService.this; } } @Override public void onCreate() { Log.d("IT_Real", "onCreate: "); super.onCreate(); } /** * 绑定服务时调用该方法 * @param intent * @return */ @Override public IBinder onBind(Intent intent) { Log.d("IT_Real", "onBind: "); return new MyBinder(); } @Override public boolean onUnbind(Intent intent) { Log.d("IT_Real", "onUnbind: "); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d("IT_Real", "onDestroy: "); super.onDestroy(); } }
这样我们就可以获取绑定服务对象了。然后我们看一下下面的生命周期图
通过绑定服务我们可以看出该生命周期。当调用了bindService方法时,生命周期为onCreate()——>onBind()——>服务运行,当调用unbindService()方法时,服务被关闭,执行onUnbind()——>onDestroy()
通过绑定服务,我们可以获取到对应的服务对象,如果说要实现某些操作,在服务里面定义对应的该操作,然后通过服务对象可以去调用该方法。我们去调用一个播放、暂停、上一首、下一首等。代码如下
MainActivity.java
public class MainActivity extends AppCompatActivity { private Intent intent; private MyServiceConnection conn; private MyBindService service2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); conn = new MyServiceConnection(); } public void onClick(View view){ intent = new Intent(this,MyBindService.class); switch (view.getId()) { case R.id.bindStart: bindService(intent,conn,BIND_AUTO_CREATE); break; case R.id.bindStop: unbindService(conn); break; case R.id.startMusic: //播放 service2.start(); break; case R.id.pause: //暂停 service2.pause(); break; case R.id.previous: //上一首 service2.previous(); break; case R.id.next: //下一首 service2.next(); break; } } /** * ServiceConnection类,通过该类中的onServiceConnected方法 * 中的IBinder service对象可以获取到绑定的服务对象中的MyBinder对象 * 然后可以通过MyBinder对象中的getBindService方法获取我们的 * MyBindService对象 */ class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取Binder对象 MyBindService.MyBinder service1 = (MyBindService.MyBinder) service; service2 = service1.getBindService(); } @Override public void onServiceDisconnected(ComponentName name) { } } }
MyBindService.java
public class MyBindService extends Service { public MyBindService() { } /** * 返回的IBinder对象 */ class MyBinder extends Binder{ public MyBindService getBindService(){ return MyBindService.this; } } /** * 服务被创建时调用该方法 */ @Override public void onCreate() { Log.d("IT_Real", "onCreate: "); super.onCreate(); } /** * 绑定服务时调用该方法 * @param intent * @return */ @Override public IBinder onBind(Intent intent) { Log.d("IT_Real", "onBind: "); return new MyBinder(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("IT_Real", "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } /** * 当调用了unbindService方法是,调用该方法 * @param intent * @return */ @Override public boolean onUnbind(Intent intent) { Log.d("IT_Real", "onUnbind: "); return super.onUnbind(intent); } /** * 被关闭之前调用该方法 */ @Override public void onDestroy() { Log.d("IT_Real", "onDestroy: "); super.onDestroy(); } public void start(){ Log.d("IT_Real", "start: 播放"); } public void pause(){ Log.d("IT_Real", "pause: 暂停"); } public void next(){ Log.d("IT_Real", "next: 下一首"); } public void previous(){ Log.d("IT_Real", "previous: 上一首"); } }
这样就可以很好的操作服务里面的方法了。对于绑定服务,有一个地方需要注意,那就是,我们在启动服务后,如果退出了当前activity,或者结束该进程的时候,没有调用unbindService()方法,程序会报一个
Activity cn.itrealman.servicedemo.MainActivity has leaked ServiceConnectioncn.itrealman.service demo.MainActivity$MyServiceConnection@6c1837b that was originally bound here异常
这个异常表示连接已经绑定,我们没有解绑,会导致泄露问题。所以,一般我们建议在销毁Activity时,我们需要在Activity的onDestroy()方法中添加如下代码:
@Override protected void onDestroy() { unbindService(conn); super.onDestroy(); }
或者说,我们在关闭Activity之前,自己手动调用解绑方法。这样就能保证我们的程序不出错。
相关文章推荐
- Android 四大组件学习之 Service 服务
- Android笔记---四大组件之Service服务详解
- Android 学习笔记 —— Android 四大组件 与 MVC 架构模式
- android service 服务学习笔记
- #Android笔记#四大组件之Service
- Android学习日志11__四大组件02__service
- android 四大组件之service学习总结(二)
- 【Android四大组件之Service】(一)Android中Service(服务)的官方介绍
- Android 编程下的四大组件之服务(Service)
- Android四大组件之一Service介绍-android学习之旅(十二)
- Android四大基本组件(2)之Service 服务与Content Provider内容提供者
- 黑马程序员------学习笔记(10)Android四大组件
- Android四大组件服务(Service)
- Android四大组件之Service(笔记)续
- Android重要组件之一 Service 服务讲解学习(一)
- Android四大组件之一Service(服务)
- android 四大组件之service学习总结(一)
- Android 学习笔记 - 【Android应用程序四大组件】
- Java乔晓松-android的四大组件之一Service(服务的绑定)
- Android成长日记-Android四大组件之Service组件的学习