Android 绑定 Service
上一章节我们介绍了 startService()
方式启动一个非绑定的 Service
,我们发现 onBind()
方法并没有被调用
本章节我们来学习下 bindService()
方式启动一个 Service
bindService() 启动 Service
bindService(Intent Service,ServiceConnection conn,int flags)
参数 | 说明 |
---|---|
service | 通过该 Intent 指定要启动的 Service |
conn | ServiceConnection 对象,用户监听访问者与 Service 间的连接情况,连接成功回调该对象中的 onServiceConnected(ComponentName,IBinder) 方法;如果 Service 所在的宿主由于异常终止或者其它原因终止,导致 Service 与访问者间断开连接时调用 onServiceDisconnected(CompanentName ) 方法,主动通过 unBindService() 方法断开并不会调用上述方法 |
flags | 指定绑定时是否自动创建 Service** (如果 Service 还未创建),参数可以是 0(不自动创建),BIND_AUTO_CREATE (自动创建) |
-
当首次使用
bindService()
绑定一个 Service 时,系统会实例化一个 Service 实例,并调用其onCreate()
和onBind()
方法,然后调用者就可以通过 IBinder 和 Service 进行交互了,此后如果再次使用bindService()
绑定 Service,系统不会创建新的 Sevice 实例,也不会再调用onBind()
方法,只会直接把 IBinder 对象传递给其他后来增加的客户端 -
想要解除与服务的绑定,只需调用
unbindService()
,此时onUnbind()
和onDestory()
方法将会被调用这是一个客户端的情况,假如是多个客户端绑定同一个 Service 的话, 那么当一个客户完成和 service 之间的互动后,它调用
unbindService()
方法来解除绑定当所有的客户端都和 service 解除绑定后,系统会销毁 Service (除非 Service 也被
startService()
方法开启) -
与
startService()
不同的是,bindService()
模式下的 Service 是与调用者相互关联的,可以理解为 "一条绳子上的蚂蚱", 要死一起死, 在bindService()
后,一旦调用者销毁,那么 Service 也立即终止 -
onServiceConnected()
方法中有一个 IBinder 对象,该对象即可实现与被绑定 Service 之间的通信我们实现 Service 类时,默认需要实现 IBinder
onBind()
方法,该方法返回的 IBinder 对象会传到 ServiceConnection 对象中的onServiceConnected
的参数就可以在这里通过这个IBinder与Service进行通信
也就是说
- 在自定义的 Service 中继承 Binder,实现自己的 IBinder 对象
- 通过
onBind()
方法返回自己的 IBinder 对象 - 在绑定该 Service 的类中定义一个 ServiceConnection 对象,重写两个方法
onServiceConnected()
和onDisconnected()
然后直接读取 IBinder 传递过来的参数即可
验证 BindService 启动 Service 的顺序
我们写一个 demo 用 bindService()
开发一个用来计时的 Service 用来演示 bindService()
的用法以及方法调用流程
-
创建一个 空的 Android 项目
cn.twle.android.BindService
-
在
MainActivity.java
目录下新建一个 ServiceMsTestService.java
package cn.twle.android.bindservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.Binder; import android.util.Log; public class MsTestService extends Service { private final String TAG = "MsTestService"; private int count; private boolean quit; //定义onBinder方法所返回的对象 private MsBinder binder = new MsBinder(); public class MsBinder extends Binder { public int getCount() { return count; } } //必须实现的方法,绑定改Service时回调该方法 @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind方法被调用!"); return binder; } //Service被创建时回调 @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate方法被调用!"); //创建一个线程动态地修改count的值 new Thread() { public void run() { while(!quit) { try { Thread.sleep(1000); }catch(InterruptedException e){e.printStackTrace();} count++; } }; }.start(); } //Service断开连接时回调 @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind方法被调用!"); return true; } //Service被关闭前回调 @Override public void onDestroy() { super.onDestroy(); this.quit = true; Log.i(TAG, "onDestroyed方法被调用!"); } @Override public void onRebind(Intent intent) { Log.i(TAG, "onRebind方法被调用!"); super.onRebind(intent); } }
-
修改
AndroidManifest.xml
完成Service
注册,在</activity>
后添加<!-- 配置 Service 组件,同时配置一个 action --> <service android:name=".MsTestService"> <intent-filter> <action android:name="cn.twle.android.bindservice.MS_TEST_SERVICE"/> </intent-filter> </service>
-
修改
activity_main.xml
添加两个按钮<?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="horizontal" > <Button android:text="锁定 Service" android:id="@+id/service_lock" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:text="解除锁定" android:id="@+id/service_unlock" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:text="获取状态" android:id="@+id/service_status" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
-
修改
MainActivity.java
package cn.twle.android.bindservice; import android.app.Service; import android.support.v7.app.AppCompatActivity; import android.content.Intent; import android.content.ComponentName; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.util.Log; public class MainActivity extends AppCompatActivity { //保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象 MsTestService.MsBinder binder; private ServiceConnection conn = new ServiceConnection() { // Activity 与 Service 断开连接时回调该方法 @Override public void onServiceDisconnected(ComponentName name) { Log.i("MsTestService","------Service DisConnected-------"); } // Activity 与 Service 连接成功时回调该方法 @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.i("MsTestService","------Service Connected-------"); binder = (MsTestService.MsBinder) service; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button service_lock = (Button) findViewById(R.id.service_lock); Button service_unlock = (Button) findViewById(R.id.service_unlock); Button service_status = (Button) findViewById(R.id.service_status); final Intent it = new Intent(this,MsTestService.class); service_lock.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //绑定service bindService(it, conn, Service.BIND_AUTO_CREATE); } }); service_unlock.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //解除service绑定 unbindService(conn); } }); service_status.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "Service的count的值为:" + binder.getCount(), Toast.LENGTH_SHORT).show(); } }); } }
运行效果如下
点击锁定 Service
继续点击锁定:没任何变化
获取当前 Service 的状态
解除绑定
如果我们再绑定后直接关掉 Activity ,会自动调用 onUnbind
和 onDestory()
方法
从运行结果可以看出
使用 bindService
绑定 Service,依次调用 onCreate()
,onBind()
方法
我们可以在 onBind()
方法中返回自定义的 IBinder 对象;
再接着调用的是 ServiceConnection 的 onServiceConnected()
方法该方法中可以获得
IBinder 对象,从而进行相关操作;
当 Service 解除绑定后会自动调用 onUnbind()
和 onDestroyed()
方法
如果绑定多客户端情况需要解除所有的绑定才会调用 onDestoryed()
方法进行销毁