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;