Android Activity与Service数据交互:Binder、bindService(系列2)

在实际的开发中,往往通过Android的Service把后台任务完成后,需要将结果传递给上层代码,比如一个Activity启动了Service,当Service在后台完成处理操作后,此时Service需要将结果传递给Activity,该怎么办呢?办法很多,其中一个就是使用和Android Service密切相关的Android Binder。
假设一个场景,前台Activity需要做一个计算任务,计算任务很简单,计算两个数值的和a+b=?(在实际开发中,这是不存在的,举这个a+b的场景只是为了举一反三用简单例子说没问题)。我将这个计算过程放到Service里面做,首先需要给Service传递过去a与b的值,然后启动Service的服务计算a+b,接下来Service计算完毕得到结果后,Activity再从Service里面获得计算结果,整个Activity与Service交互至此结束。
但是这个看似简单却在Activity与Service中如果不用bind的模型传递数据将会变得复杂,原因在于当Activity启动Service后,从此Activity与Service天地相隔,不存在太大关系,不能像普通的类一样操作Service及里面的方法体。
下面就用Service的bind解决。
这篇文章是在上一篇文章《Android Service简介(系列1)》(文章链接:http://blog.csdn.net/zhangphil/article/details/49373939 )的基础上增加bind机制。

大致上Activity与Service通过bind交互的编程模型是:
(第1步)老规矩,还是先继承Service。完成里面的onBind,返回一个自己重写的Binder,在本例中是MyBinder。MyBinder里面一个public get方法返回Service的类实例。
毫无疑问,同时需要在Service里面写好public set/get方法,为后面的Activity访问做好基本set/get操作。
(第2步)在Activity里面bindService。bindService是为了将Activity和Service绑定在一起,大有不求同年同月生,但求同年同月死的味道。
在bindService的时候,需要传递一个ServiceConnection,ServiceConnection像一个桥梁,建立了Activity和Service之间的桥接。事实上也就是为了从ServiceConnection的回调方法onServiceConnected中的获得后台的Service句柄。只要获得Service的句柄,那么什么都好办了。
(第3步)在Activity中拿到Service的句柄后,就可以像操作一个普通的Java类一样传参、取值了。

以上步骤完成后,需要明确一个基本的Activity使用Service的顺序流程,以计算a+b=?为例:
(A)首先需要在Activity里面bindService。bindService时候需要传递过去ServiceConnection,在ServiceConnection的回调方法onServiceConnected中获得Service句柄。
(B)拿到Service句柄后,在Activity中设置Service里面的a与b的值。
(C)startService。startService将跳过onCreate直接进入onStartCommand方法体内,在Service里面的后台操作,也可以简单理解为就是在Service的onStartCommand中的操作。在onStartCommand中计算a+b的和。
(D)上层Activity再次通过之前获得的Service句柄从Service里面get a+b的和。

以上模型和流程的代码实现:
Service类:

package zhangphil.service;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;public class MyAppService extends Service {private int a = 0, b = 0;private int result = 0;@Overridepublic void onCreate() {Log.d(this.getClass().getName(), "onCreate");}// 需要Service处理的操作在此@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {result = a + b;Log.d(this.getClass().getName(), "onStartCommand:" + result);return super.onStartCommand(intent, flags, startId);}public int getServiceValue() {return result;}public void setServiceValue(int a, int b) {this.a = a;this.b = b;Log.d(this.getClass().getName(), "setServiceValue:a=" + a + " b=" + b);}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}public class MyBinder extends Binder {public MyAppService getService() {return MyAppService.this;}}@Overridepublic boolean onUnbind(Intent intent) {Log.d(this.getClass().getName(), "onUnbind");return super.onUnbind(intent);}@Overridepublic void onDestroy() {Log.d(this.getClass().getName(), "onDestroy");}}



测试的Activity MainActivity:

package zhangphil.service;import java.util.Random;import android.app.Activity;import android.app.Service;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.Toast;import zhangphil.service.MyAppService.MyBinder;public class MainActivity extends Activity {private ServiceConnection sc = null;private MyAppService myAppService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button start = (Button) findViewById(R.id.start);start.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startMyAppService();}});Button bind = (Button) findViewById(R.id.bind);bind.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {bindMyAppService();}});Button unbind = (Button) findViewById(R.id.unbind);unbind.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {unbindMyAppService();}});Button set = (Button) findViewById(R.id.set);set.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Random rand = new Random();int a = rand.nextInt(10);int b = rand.nextInt(10);myAppService.setServiceValue(a, b);}});Button result = (Button) findViewById(R.id.result);result.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(getApplicationContext(), myAppService.getServiceValue() + "", Toast.LENGTH_SHORT).show();}});Button stop = (Button) findViewById(R.id.stop);stop.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {stopMyAppService();}});}@Overrideprotected void onDestroy() {super.onDestroy();unbindMyAppService();Log.d(this.getClass().getName(), "onDestroy");}private void startMyAppService() {Intent intent = new Intent(this, MyAppService.class);this.startService(intent);}private void bindMyAppService() {sc = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(this.getClass().getName(), "onServiceConnected");MyBinder mBinder = (MyBinder) service;myAppService = mBinder.getService();}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(this.getClass().getName(), "onServiceDisconnected");}};Intent intent = new Intent(this, MyAppService.class);this.bindService(intent, sc, Service.BIND_AUTO_CREATE);}private void stopMyAppService() {Intent intent = new Intent(this, MyAppService.class);boolean bool = this.stopService(intent);}private void unbindMyAppService() {if (sc != null)this.unbindService(sc);}}


注意记到!在Activity退出时候,请unbindService,或者stopService。

更多相关文章

  1. Android(安卓)SQLite使用SQLiteOpenHelper类对数据库进行操作
  2. Android按钮文字变色(使用 ColorStateList)
  3. Android(安卓)开发中,有哪些坑需要注意?
  4. Android通过AIDL实现接听电话、挂断电话操作 | 拨打电话
  5. 自定义Drawable
  6. Android事件处理--读书笔记
  7. Android(安卓)获取并显示远程图片 Picasso框架的使用(一)
  8. Android线程阻塞处理及优化
  9. Android(安卓)DiskLruCache完全解析,硬盘缓存的最佳方案

随机推荐

  1. MySQL查询截取的深入分析
  2. mysql、oracle默认事务隔离级别的说明
  3. MySQL 事务autocommit自动提交操作
  4. MySQL多表查询的具体实例
  5. MySQL 查看事务和锁情况的常用语句分享
  6. mysql单字段多值分割和合并的处理方法
  7. MySQL中外键的创建、约束以及删除
  8. 简单谈谈mysql左连接内连接
  9. Mysql合并结果接横向拼接字段的实现步骤
  10. 你知道mysql中空值和null值的区别吗