Android Activity与Service数据交互:Binder、bindService

在实际的开发中,往往通过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解决。

大致上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 com.example.binder;

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 he=0;		
	
	@Override
	public void onCreate(){
		Log.d(this.getClass().getName(), "oncreate");
	}
	
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		
			he=a+b;
		Log.d(this.getClass().getName(), "onStartCommand"+he);	
		return super.onStartCommand(intent, flags, startId);
	}
	
	public int getServicehe(){
		return he;
		
	}
	public void setServicehe(int a,int b){
		this.a=a;
		this.b=b;
		Log.d(this.getClass().getName(), "setServicehe"+"a="+a+"b="+b);
	}

	@Override
	public IBinder onBind(Intent intent) {
		
		
		return new Mybinder();
	}
	public class Mybinder extends Binder{
		
		public MyAppservice getservice(){
			
			return MyAppservice.this;
			
		}
	}
	@Override
	public boolean onUnbind(Intent intent) {
		
		return super.onUnbind(intent);
	}
	public  void onDestroy(){
		super.onDestroy();
	}
}
测试的Activity MainActivity:

package com.example.binder;

import com.example.binder.MyAppservice.Mybinder;

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.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{

	private ServiceConnection sc=null;
	private MyAppservice myappservice=null;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
	Button bt1=(Button) findViewById(R.id.button1);
		   bt1.setOnClickListener(MainActivity.this);
	Button bt2=(Button) findViewById(R.id.button2);
		   bt2.setOnClickListener(MainActivity.this);
	Button bt3=(Button) findViewById(R.id.button3);
		   bt3.setOnClickListener(MainActivity.this);	   
		
		   sc=new ServiceConnection() {
				
				@Override
				
				public void onServiceConnected(ComponentName name, IBinder service) {
					
					Log.d(this.getClass().getName(),"onServiceConnected");
					Mybinder binder=(Mybinder) service;
					myappservice=binder.getservice();
					
					
				}
				@Override
				public void onServiceDisconnected(ComponentName name) {
					
				Log.d(this.getClass().getName(), "onServiceDisconnected");
					
				}
				
			};
	}
	@Override
	public void onClick(View v) {
		if(v.getId()==R.id.button1){
			startAppserivce();
		}
		
	 if(v.getId()==R.id.button2){
			bangdingAppserivce();
		}
		
	}
	private void startAppserivce(){
		myappservice.setServicehe(5, 8);
		
		Intent intent=new Intent(this,MyAppservice.class);
		this.startService(intent);
	}
	private void bangdingAppserivce(){
		
		Intent intent=new Intent(this,MyAppservice.class);
		this.bindService(intent,sc,Service.BIND_AUTO_CREATE);
	}
	
	private void quzhiService(){
		if(sc!=null){
			Intent intent=new Intent(this,MyAppservice.class);
			this.unbindService((ServiceConnection) intent);
		}
	}
	public   void  onDestroy(){
		super.onDestroy();

		Intent intent = new Intent(this, MyAppservice.class);
		stopService(intent);
	}
	
}



你可能感兴趣的:(代码)