android activity和service的交互介绍

android开发中,作为4大组件的service在开发中经常会使用到。很多时候,我们的activity和service之间需要进行相应的交互,activity需要调用service里面的方法实现某些功能,service需要调用activity的方法,实现界面更新等的交互。


实现2者之间相互交互的主要方式是:service中有个类部类继承Binder,然后提供一个公有方法,返回当前service的实例。 activity通过bindService来开启一个service,service通过onBind方法,返回一个IBinder实例(我们创建的那个类部类实例),activity中通过onServiceConnected方法,获取IBinder实例,然后再通过IBinder实例来获取service实例,这样,我们得到了service的实例,那么我们的activity就可以随心所欲的使用它里面的各种方法来操作它了。



上面activity可以操作service了,我们还需要service能操作activity。

我觉得可以有3中方式:

1.直接把activity传给service,service通过activity实例随便操作activity

2.使用接口回调方式,activity实现相应的接口,service通过接口进行回调,比较灵活

3.使用广播


使用广播是比较常见的方式,我们就不具体讲解了,下面我们介绍前面2中方法,具体看代码,用service更新seekbar。

我们的activity代码:

package com.hck.bindservice;

import android.app.Activity;
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.SeekBar;
import android.widget.Toast;

import com.hck.bindservice.MyService.MyBuild;

public class MainActivity extends Activity {
   private MyService myService;  //我们自己的service
   private SeekBar pBar;  //模拟service更新进度条
   private ConnectionService connectionService;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		pBar = (SeekBar) findViewById(R.id.seekbar);
		connectionService=new ConnectionService();   
	}

	public void startService(View view) { //绑定service
       bindService(new Intent(this,MyService.class), connectionService, 1);
	}
	/**
	 * 
	 * @author Administrator
	 *实现service接口,用于service绑定时候,回调
	 */
	class ConnectionService  implements ServiceConnection
	{
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			myService=((MyBuild)service).getMyService(); //获取Myservice对象
			
			/**
			 * 直接把当前对象传给service,这样service就可以随心所欲的调用本activity的各种可用方法
			 */
			myService.setMainActivity(MainActivity.this); //把当前对象传递给myservice
			
			
			/**
			 * 使用一个接口来实现回调,这样比上面方法更加灵活,推荐
			 */
//			myService.setOnProgressBarListener(new UpdateProgressListener() {
//				
//				@Override
//				public void updateBar(int size) {
//					updateBar(size);
//				}
//			});
			
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
	}
	/**
	 * 
	 * @param size
	 * 更新seekbar
	 */
	public void updateBar(int size)
	{
		pBar.setProgress(size);
	}
	
	/**
	 * 
	 * @param view
	 * 开始更新seekbar
	 */
	public void startBar(View view) {
	      if (myService==null) {
			Toast.makeText(this, "请先开始service", Toast.LENGTH_LONG).show();
		 }
	      else {
			myService.startUpdateProgress();
		}
		}
/**
 * 
 * @param view
 * 停止更新seekbar
 */
		public void stopBar(View view) {
			
			 if (myService==null) {
					Toast.makeText(this, "更新没有开始", Toast.LENGTH_LONG).show();
				 }
			      else {
					myService.stopUpdateProgress();
				}
		}
/**
 * 
 * @param view
 * 停止service
 */
		public void stopService(View view) {
			myService=null;
				unbindService(connectionService);
			
			
			
			
		}
		@Override
			protected void onDestroy() {
				super.onDestroy();
				try {
					unbindService(connectionService);
				} catch (Exception e) {
				}
				
			}


}


重要代码是onServiceConnected回调方法里面

myService=((MyBuild)service).getMyService(); //获取Myservice对象

获取service对象后,我们想怎么操作它都行了,比如上面的,把activity实例直接通过它的方法传递过去,便于

service调用activity的各种方法。或者,设置传递一个回调接口对象过去,用户回调



service代码:

package com.hck.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service{
   private int size=0;  
   private UpdateProgress updateProgress;
   private final long TIME=2000;
   private boolean isUpdate=true;
   private MainActivity activity;
   private UpdateProgressListener listener;
	@Override
	public IBinder onBind(Intent intent) {
		
		return new MyBuild();
	}
	@Override
	public void onCreate() {
		super.onCreate();
		updateProgress=new UpdateProgress();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}
	/**
	 * 
	 * @author Administrator
	 * 线程用来改变seekbar进度的大小
	 *
	 */
	class UpdateProgress implements Runnable
	{
		@Override
		public void run() {
			if (isUpdate) {
				  size+=10;
		           if (size>100) {
					size=0;
				}
		           handler.sendEmptyMessage(0);
			}
		}
	}
	/**
	 * 调用更新相应方法,更新进度条
	 */
	Handler handler=new Handler()
	{
		public void handleMessage(android.os.Message msg) {
			/**
			 * 直接调用activity对象里面的方法
			 */
			if (activity!=null) {
				activity.updateBar(size);
			}
			
			/**
			 * 使用接口回调
			 */
//			if (listener!=null) {
//				listener.updateBar(size);
//			}
			handler.postDelayed(updateProgress, TIME);
		};
	};
	
	/**
	 * 停止更新
	 */
	public void stopUpdateProgress()
	{
		isUpdate=false;
	}
	/**
	 * 开启更新
	 */
	public void startUpdateProgress()
	{
		
		if (!isUpdate) {
			handler.post(updateProgress);
		}
		isUpdate=true;
	}
	public void onDestroy() {
		isUpdate=false;
	};
	
	/**
	 * 
	 * @param activity
	 * 初始化MainActivity对象
	 */
	public void setMainActivity(MainActivity activity)
	{
		this.activity=activity;
	}
	/**
	 * 
	 * @param listener
	 * 初始化UpdateProgressListener对象
	 */
	public void setOnProgressBarListener(UpdateProgressListener listener)
	{
		this.listener=listener;
	}
	
	/**
	 * 
	 * @author Administrator
	 * 使用类部类,返回当前service的实例,用于activity,调用service的各种方法
	 *
	 */
	class MyBuild extends Binder
	{
		public MyService getMyService()
		{
			return MyService.this;
		}
	}
	

}


service里面最重要的就是,最下面我们的MyBuild类部类了,通过它的getMyService方法,获取service的实例

该类的实例实在onBind时候,我们返回给activity的。



接口:

package com.hck.bindservice;

public interface UpdateProgressListener {
 public void updateBar(int size);
}


一个简单接口,用于service回调activity



上面是使用 bindService来启动service的,那么如果我们使用startService启动service时候,上面的办法就不行了。

因为onBind不会执行,我们获取不到IBinder实例。这个时候,我们可以使用设计模式的观察者模式来处理。

其它不清楚,还有什么比较好的办法没有,我是没有想到,有知道的朋友,请告知,谢谢



例子源码:http://download.csdn.net/detail/hhhccckkk/8469069 

请把 private boolean isUpdate=true;    改为 private boolean isUpdate=false;

 





  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值