开启服务的时候,如果我们是通过bindService来绑定服务并且要向服务传递数据,可以直接在Intent中设置bundle来达到效果,但是如果是我们需要从服务中返回一些数据到Activity中的时候,实现起来就有各种各样的方法,比如说使用回调,使用广播等等,今天说的是使用回调的方法。

新建一个工程,并编写一个服务:

 public class MyService extends Service {
private boolean connecting = false;
private Callback callback; @Nullable
@Override
public IBinder onBind(Intent intent) {
return new Binder();
} public class Binder extends android.os.Binder {
public MyService getService() {
return MyService.this;
}
} @Override
public void onCreate() {
super.onCreate();
connecting = true;
new Thread(new Runnable() { @Override
public void run() {
int i = 0;
while (connecting == true) {
i++;
if (callback != null) {
callback.onDataChange(i + "");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
} public void setCallback(Callback callback) {
this.callback = callback;
} public static interface Callback {
void onDataChange(String data);
} @Override
public void onDestroy() {
super.onDestroy();
connecting = false;
}
}

在服务中的onCreate方法中,我们打开了一个线程来模拟服务的运行,并在线程每隔1s中给私有变量i赋值递增,然后我们编写了一个公有的接口Callback,并且定义了一个该接口的私有成员,并且在onCreate方法中调用了接口里面的函数onDataChange。接下来我们自定义了一个Binder的子类并在这个类中定义了函数返回当前的这个Service,这里的目的就是在Activity中可以访问到这个Service的回调接口Callback并实现该接口的方法。

Activity代码如下:

 public class MainActivity extends AppCompatActivity implements View.OnClickListener,
ServiceConnection { private TextView tvOut; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvOut = (TextView) findViewById(R.id.tvOut);
findViewById(R.id.btnBindService).setOnClickListener(this);
} @Override
public void onClick(View v) {
bindService(new Intent(this, MyService.class), this, BIND_AUTO_CREATE);
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyService.Binder binder = (MyService.Binder) service;
MyService myService = binder.getService();
myService.setCallback(new MyService.Callback() {
@Override
public void onDataChange(String data) {
Message msg = new Message();
msg.obj = data;
handler.sendMessage(msg);
}
});
} @Override
public void onServiceDisconnected(ComponentName name) { } private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tvOut.setText(msg.obj.toString());
}
};
}

因为服务绑定后,会从onBind方法中返回一个Binder对象,这个对象会在onServiceConnectde方法中获取到,所以我们先从Binder对象中获取到我们从服务传递过来的MyService对象,然后调用MyService对象的setCallback方法来设置我们需要的处理逻辑,这里是把i的值打印出来,因为服务中开启了线程,所以这里也不能直接更新UI。

总结:回调机制是Java中的一个重要特性,在Android中使用到的地方很广泛,例如我们给按钮设定点击事件等。这里的回调,其实是通过在发送端定义回调接口,并且调用接口的回调方法,然后在接收端实现该接口的方法。只要接口被调用了,就会回调接收端的被实现了的方法,这样数据就能传递过来。

注意:开启的服务是在主线程中运行的,如果在服务中开启了线程,那么在子线程中就不能直接更新UI

Android开发学习之路-回调实现Service向activity传递数据的更多相关文章

  1. Android开发学习之路-回调机制学习笔记

    不知道是我学Java的时候没有认真听还是怎么的,曾经一直不知道什么是“回调”,它有什么用,百度一大堆,都太复杂看不明白(好吧是我笨),所以想把自己理解的分享给其他看到的人,大家都真正认识一下这个重要的 ...

  2. Android开发学习之路-RecyclerView滑动删除和拖动排序

    Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...

  3. Android开发学习之路--Activity之初体验

    环境也搭建好了,android系统也基本了解了,那么接下来就可以开始学习android开发了,相信这么学下去肯定可以把android开发学习好的,再加上时而再温故下linux下的知识,看看androi ...

  4. Android开发学习之路--基于vitamio的视频播放器(二)

      终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...

  5. Android开发学习之路--Android Studio cmake编译ffmpeg

      最新的android studio2.2引入了cmake可以很好地实现ndk的编写.这里使用最新的方式,对于以前的android下的ndk编译什么的可以参考之前的文章:Android开发学习之路– ...

  6. Android开发学习之路--网络编程之xml、json

    一般网络数据通过http来get,post,那么其中的数据不可能杂乱无章,比如我要post一段数据,肯定是要有一定的格式,协议的.常用的就是xml和json了.在此先要搭建个简单的服务器吧,首先呢下载 ...

  7. Android开发学习之路--Android系统架构初探

    环境搭建好了,最简单的app也运行过了,那么app到底是怎么运行在手机上的,手机又到底怎么能运行这些应用,一堆的电子元器件最后可以运行这么美妙的界面,在此还是需要好好研究研究.这里从芯片及硬件模块-& ...

  8. Android开发学习之路--MAC下Android Studio开发环境搭建

    自从毕业开始到现在还没有系统地学习android应用的开发,之前一直都是做些底层的驱动,以及linux上的c开发.虽然写过几个简单的app,也对android4.0.3的源代码做过部分的分析,也算入门 ...

  9. Android开发学习之路-该怎么学Android(Service和Activity通信为例)

    在大部分地方,比如书本或者学校和培训机构,教学Android的方式都基本类似,就是告诉先上原理方法,然后对着代码讲一下. 但是,这往往不是一个很好的方法,为什么? ① 学生要掌握这个方法的用途,只能通 ...

随机推荐

  1. 15.Xcode8 升级遇到的问题

    一:注释快捷键cmd+/不能用,解决方法: 1. Swift_3.0 没法快捷键(command+/)注释的原因:这个是因为苹果解决xcode ghost,把插件屏蔽了. 2. 解决办法: (1) 终 ...

  2. apache安装mod_deflate配置支持gzip

    apache 配置支持gzip apache使用gzip压缩能够大幅提高网站访问速度并节省网络流量,在网页响应头信息中可以判断是否支持压缩. HTTP/1.1 200 OK Date: Wed, 14 ...

  3. CAD规划成果入库GIS_SDE转换之分析

    问题: 1) 项目应用中要求将CAD规划成果合理的入库GIS SDE中,在建立一套比较规范的标准为前提下,如何“低技术.傻瓜式”实现规划数据更新管理.版本化是个迫切难题. 2) CAD作为数据源,不同 ...

  4. gem sources --add http://ruby.taobao.org/

    gem sources  gem sources  gem sources --remove http://ruby.taobao.org/ gem sources --add http://ruby ...

  5. RabbitMQ 问题记录

    1. rabbitmq安装后无法运行,报错“unable to connect to node rabbit@XXXX: nodedown”. 怀疑局域网内有相同名称的计算机安装了rabbitmq,造 ...

  6. JavaScript中,本周、上周、本月、上月日期判断

    /** * 获取本周.本季度.本月.上月的开端日期.停止日期 */ var now = new Date(); //当前日期 var nowDayOfWeek = now.getDay(); //今天 ...

  7. java基础2_算术运算

    一 算术运算符,包括+,-,*,/,%, 1. 如果在一个算术运算中有int,double,float那么最终运算的结果是double,那么也就是说参与运算的类型和得到的结果:结果一定是参与运算的精度 ...

  8. Unity3d中Update()方法的替身

    在网上看到一些资料说Unity3d的Update方法是如何如何不好,影响性能.作为一个菜鸟,之前我还觉得挺好用的,完全没用什么影响性能的问题存在.现在发现确实有很大的问题,我习惯把一大堆检测判断放在U ...

  9. MyEclipse 自带的TomCat 新增部署的时候不显示 Deploy Location

    项目总是报错,添了删,删了又添了N次以后,发现添加部署的时候,Deploy Location 没有值了,Deploy Location 没有值在自带的Tomcat上就无法用浏览器浏览(Open in ...

  10. C++混合编程之idlcpp教程Python篇(8)

    上一篇在这 C++混合编程之idlcpp教程Python篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial6中,同样加入了四个文件:Pyt ...