android Service和Activity的通信

来源:互联网 发布:故事版绘制软件 编辑:程序博客网 时间:2024/06/05 22:37

android Service和Activity的通信大致有三种方法:
- 通过Binder对象
- 通过回调方法
- 通过广播

我们通过在service中下载通知activity进度的例子说明。

一、通过Binder对象
首先在service中写一个方法
public int getProgress() {
return progress;
}
用于在activity中调用这个方法得到进度,并且在线程中不断更新progress。

public class MsgService extends Service {

private int progress=0;public class MyBinder extends Binder{    /**     * 获取当前Service的实例     * @return     */    public MsgService getService(){        return MsgService.this;    }}@Overridepublic IBinder onBind(Intent intent) {    return new MyBinder();}/** * 模拟下载任务,每秒钟更新一次 */public void startDownLoad(){    new Thread(new Runnable() {        @Override        public void run() {                progress += 5;                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }        }    }).start();}/** * 增加get()方法,供Activity调用 * @return 下载进度 */public int getProgress() {    return progress;}

}

然后在activity中绑定service,并获取到service的实例

private MsgService msgService;private ServiceConnection connection=new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder service) {        msgService= ((MsgService.MyBinder) service).getService();    }    @Override    public void onServiceDisconnected(ComponentName name) {    }};

最后在activity中开启一个线程不断的调用service中的getService()方法获取进度

public class MainActivity extends AppCompatActivity {

private int progress = 0;private MsgService msgService;private ServiceConnection connection=new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder service) {        msgService= ((MsgService.MyBinder) service).getService();    }    @Override    public void onServiceDisconnected(ComponentName name) {    }};@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    Intent intent=new Intent(this,MsgService.class);    bindService(intent, connection, BIND_AUTO_CREATE);}/** * 监听进度,每秒钟获取调用MsgService的getProgress()方法来获取进度 */public void listenProgress(){    new Thread(new Runnable() {        @Override        public void run() {                progress = msgService.getProgress();                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }        }    }).start();}@Overrideprotected void onDestroy() {    super.onDestroy();    unbindService(connection);}

}

二、通过回调方法
上面的代码就完成了在Service更新UI的操作,可是你发现了没有,我们每次都要主动调用getProgress()来获取进度值,然后隔一秒在调用一次getProgress()方法,你会不会觉得很被动呢?可不可以有一种方法当Service中进度发生变化主动通知Activity,答案是肯定的,我们可以利用回调接口实现Service的主动通知

首先建立一个接口

public interface OnProgressListener {
void onProgress(int progress);
}
然后在MsgService中加入以下代码:
/**
* 更新进度的回调接口
*/
private OnProgressListener onProgressListener;

/**
* 注册回调接口的方法,供外部调用
* @param onProgressListener
*/
public void setOnProgressListener(OnProgressListener onProgressListener) {
this.onProgressListener = onProgressListener;
}

**
* 模拟下载任务,每秒钟更新一次
*/
public void startDownLoad(){
new Thread(new Runnable() {

        @Override        public void run() {                progress += 5;                //进度发生变化通知调用方                  if(onProgressListener != null){                      onProgressListener.onProgress(progress);                  }                  try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }        }    }).start();}

这样在activity中获取到service实例后就可以在回调方法中更新进度

ServiceConnection conn = new ServiceConnection() {      @Override      public void onServiceDisconnected(ComponentName name) {      }      @Override      public void onServiceConnected(ComponentName name, IBinder service) {          //返回一个MsgService对象          msgService = ((MsgService.MsgBinder)service).getService();          //注册回调接口来接收下载进度的变化          msgService.setOnProgressListener(new OnProgressListener() {              @Override              public void onProgress(int progress) {                  mProgressBar.setProgress(progress);              }          });      }  };  

用回调接口是不是更加的方便呢,当进度发生变化的时候Service主动通知Activity,Activity就可以更新UI操作了

三、通过广播

这一种方法就比较简单,只需要在activity中注册一个广播接收器接收service发送过来的广播就可以更新进度了

在activity中注册广播

/**
* 广播接收器
* @author len
*
*/
public class MsgReceiver extends BroadcastReceiver{

    @Override      public void onReceive(Context context, Intent intent) {          //拿到进度,更新UI          int progress = intent.getIntExtra("progress", 0);      }  }  

//动态注册广播接收器
MsgReceiver msgReceiver = new MsgReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(“com.example.communication.RECEIVER”);
registerReceiver(msgReceiver, intentFilter);

在service中发送广播

//发送Action为com.example.communication.RECEIVER的广播
Intent intent = new Intent(“com.example.communication.RECEIVER”);
intent.putExtra(“progress”, progress);
sendBroadcast(intent);

总结:
*Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法
*Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好

参考自http://blog.csdn.net/xiaanming/article/details/9750689

0 0
原创粉丝点击