要实现service与activity的高强度通信用什么方法?

  service与activity之前的通信方式有很多,回调接口方式、观察者模式、广播、还有handler等,方法有很多,但要高强度地通信,个人觉得还是用回调接口的方式比较妥当(虽然本人开始也是用的传入的handler。。。哈哈,用handler的话,如果涉及到service要向多个activity传送数据就变得麻烦了)。所以在这里记录下回调接口的方式进行通信:

1、怎样在启动一个Service时向它传递数据

  关键点:Intent传值,onStartCommand()接收。

  2、怎样向运行的Service中同步数据

  关键点:通过onBind()获取Service实例,然后再调用Binder中的相关方法。

  3、怎样侦听Service中数据变化

  关键点:通过回调函数达到目的。

一、准备Service

  先贴出Service的详细代码,然后再慢慢分析


import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Binder;
public class MyService extends Service {
private String data = "默认消息";
private boolean serviceRunning = false; // 必须实现的方法,用于返回Binder对象
@Override
public IBinder onBind(Intent intent) {
System.out.println("--onBind()--");
return new MyBinder();
} public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
} public void setData(String data) {
MyService.this.data = data;
}
} // 创建Service时调用该方法,只调用一次
@Override
public void onCreate() {
super.onCreate();
System.out.println("--onCreate()--");
serviceRunning = true;
new Thread() {
@Override
public void run() {
int n = 0;
while (serviceRunning) {
n++;
String str = n + data;
System.out.println(str);
if (dataCallback != null) {
dataCallback.dataChanged(str);
}
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
} // 每次启动Servcie时都会调用该方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--onStartCommand()--");
data = intent.getStringExtra("data");
return super.onStartCommand(intent, flags, startId);
} // 解绑Servcie调用该方法
@Override
public boolean onUnbind(Intent intent) {
System.out.println("--onUnbind()--");
return super.onUnbind(intent);
} // 退出或者销毁时调用该方法
@Override
public void onDestroy() {
serviceRunning = false;
System.out.println("--onDestroy()--");
super.onDestroy();
} DataCallback dataCallback = null; public DataCallback getDataCallback() {
return dataCallback;
} public void setDataCallback(DataCallback dataCallback) {//注意这里以单个回调为例  如果是向多个activity传送数据 可以定义一个回调集合 在此处进行集合的添加
this.dataCallback = dataCallback;
} // 通过回调机制,将Service内部的变化传递到外部
public interface DataCallback {
void dataChanged(String str);
} }

 代码分析:我们都知道,通过startService启动一个Service时,Service会调用生命周期函数onStartCommand(),在代码中创建一个Service,在onStartCommand()方法中获取从Activity传递过来的数据,并在Service的onCreate()方法中开启一个新的线程,使其循环调用回调函数,以达到通知外界信息改变的目的。并在Service中通过Binder类,将Service与Activity链接起来,以实现信息同步。

二、准备布局文件

  布局文件比较简单,直接贴出,就不分析了,activity_main.xml如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TextView
android:id="@+id/tv_out"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="显示区域" /> <EditText
android:id="@+id/et_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" > <requestFocus />
</EditText> <Button
android:id="@+id/btn_start_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="startService" /> <Button
android:id="@+id/btn_stop_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="stopService" /> <Button
android:id="@+id/btn_bind_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="bindService" /> <Button
android:id="@+id/btn_unbind_service"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="unbindService" /> <Button
android:id="@+id/btn_sync_data"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="同步数据" /> </LinearLayout>

三、准备Activity

  MainActivity代码如下:

public class MainActivity extends Activity implements OnClickListener {

    private Intent intent = null;
private Button btn_start_service;
private Button btn_stop_service;
private Button btn_bind_service;
private Button btn_unbind_service;
private Button btn_sync_data;
private EditText et_data;
private TextView tv_out;
MyServiceConn myServiceConn;
MyService.MyBinder binder = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, MyService.class);
myServiceConn = new MyServiceConn();
setOnClick();
} @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start_service:
//用intent启动Service并传值
intent.putExtra("data", et_data.getText().toString());
startService(intent);
break;
case R.id.btn_stop_service:
//停止Service
stopService(intent);
break;
case R.id.btn_bind_service:
//绑定Service
bindService(intent, myServiceConn, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_unbind_service:
//解绑Service
if (binder != null) {
unbindService(myServiceConn);
}
break;
case R.id.btn_sync_data:
//注意:需要先绑定,才能同步数据
if (binder != null) {
binder.setData(et_data.getText().toString());
}
break;
default:
break;
}
} class MyServiceConn implements ServiceConnection {
// 服务被绑定成功之后执行
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// IBinder service为onBind方法返回的Service实例
binder = (MyService.MyBinder) service;
binder.getService().setDataCallback(new MyService.DataCallback() {
//执行回调函数
@Override
public void dataChanged(String str) {
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("str", str);
msg.setData(bundle);
//发送通知
handler.sendMessage(msg);
}
});
} @SuppressLint("HandlerLeak")
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
//在handler中更新UI
tv_out.setText(msg.getData().getString("str"));
};
}; // 服务奔溃或者被杀掉执行
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
} private void loadUI() {
btn_start_service = (Button) findViewById(R.id.btn_start_service);
btn_stop_service = (Button) findViewById(R.id.btn_stop_service);
btn_bind_service = (Button) findViewById(R.id.btn_bind_service);
btn_unbind_service = (Button) findViewById(R.id.btn_unbind_service);
btn_sync_data = (Button) findViewById(R.id.btn_sync_data);
et_data = (EditText) findViewById(R.id.et_data);
tv_out = (TextView) findViewById(R.id.tv_out);
} private void setOnClick() {
loadUI();
btn_start_service.setOnClickListener(this);
btn_stop_service.setOnClickListener(this);
btn_bind_service.setOnClickListener(this);
btn_unbind_service.setOnClickListener(this);
btn_sync_data.setOnClickListener(this);
} }

代码分析:

  1、加载UI,初始化变量啥的跳过了,主要说一下关键代码,在第28代码中,与启动一个Activity类似,通过Intent想要启动的Service传递参数。

  2、在37行通过bindService绑定Service,然后在ServiceConnection中获取Service类中onBind方法返回的实例,获取实例Service实例后,我们就可以通过调用Service中MyBinder的setData()方法对Service进行同步数据,如48行所示。

  3、整个过程,在Service的onCreate方法中都会循环调用回调函数,同时我们在MainActivity中重写回调方法以实现更新UI。

四、测试

  1、启动示例后,在输入框输入你好,然后点击startService,界面和对应的日志如下:

    

  看了下面的代码后就会知道,此时因为没有绑定service,所以办法执行回调函数更新UI,所以显示区域没有更新。

  2、点击bindService后,界面如下:

  

  当执行bindService后,在ServiceConnection方法中就会执行执行回调函数更新UI,此时显示区域开始更新。

  3、改变输入框内容,点击同步数据,界面和对应的日志如下:

   

Service与Activity通信 回调方式***的更多相关文章

  1. Android学习笔记(九)一个例子弄清Service与Activity通信

    上一篇博文主要整理了Service的创建.绑定过程,本篇主要整理一下Service与Activity的通信方式.包括在启动一个Service时向它传递数据.怎样改变运行中的Service中得数据和侦听 ...

  2. 本地/远程Service 和Activity 的交方式(转)

    android SDK提供了Service,用于类似*nix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remo ...

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

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

  4. activity 与 service 之间的通信

    activity和service通信:通过binder 举个我实际项目中的例子:在service中下载更新应用 首先是下载更新apk的service: public class UpdateVersi ...

  5. android开发之使用Messenger实现service与activity交互

    service与activity交互的方式有多种,这里说说使用Messenger来实现两者之间的交互. Service程序 public class MessengerService extends ...

  6. Android Service与Activity之间通信的几种方式

    在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会常常遇到Activity与Service之间的通信,我们一般在Activ ...

  7. Activity与Service通信的方式有三种:

    在博客园看到的,看着挺不错的,借来分享下 继承Binder类 这个方式仅仅有当你的Acitivity和Service处于同一个Application和进程时,才干够用,比方你后台有一个播放背景音乐的S ...

  8. Android中Service与多个Activity通信

    由于项目需要,我们有时候需要在service中处理耗时操作,然后将结果发送给activity以更新状态.通常情况下,我们只需要在一个service与一个activity之间通信,通常这种情况下,我们使 ...

  9. Android Service与Activity之间通信

    主要分为: 通过Binder对象 通过broadcast(广播)的形式 Activity调用bindService (Intent service, ServiceConnection conn, i ...

随机推荐

  1. SQL Text Literals 文本

    Text Literals 文本 Use the text literal notation to specify values whenever string appears in the synt ...

  2. JavaScript 解决 url 中的中文乱码问题

    页面传值过程中,通过 url 传值,发现中文会乱码. 以下是解决方法: 1.传的页面: encodeURI(url + "?userName=" + userName); //en ...

  3. docker启动报错解决及分析(Cannot create container for service *******: cannot mount volume over existing file, file exists /var/lib/docker/overlay2/)

    现象: Cannot create container for service *******: cannot mount volume over existing file, file exists ...

  4. Docker CMD ENTRYPOING 和Kubernetes command args对比

    Docker CMD ENTRYPOING 和Kubernetes command args对比 exec 模式 使用 exec 模式时,容器中的任务进程就是容器内的 1 号进程 shell 模式 使 ...

  5. 完美快速解决百度分享不支持HTTPS的问题

    百度分享不支持HTTPS这件事由来已久,我之前向百度分享提交过这个问题,无果!但近期themebetter主题用户咨询的比较多,我们就总结了解决方案. 第一步:下载百度分享必备文件 点此下载stati ...

  6. 原生ajax解析&封装原生ajax函数

    前沿:对于此篇随笔,完是简要写了几个重要的地方,具体实现细节完在提供的源码做了笔记 <一>ajax基本要点介绍--更好的介绍ajax 1. ajax对象中new XMLHttpReques ...

  7. 动手搭建codecombat服务

    # 因为后面需要使用浏览器访问 127.0.0.1:3000去获取管理员控制权,所以需要一个图形化的界面. yum install net-tools -y   yum groupinstall &q ...

  8. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  9. 【Miscalculation UVALive - 6833 】【模拟】

    题目分析 题目讲的是给你一个串,里面是加法.乘法混合运算(个人赛中误看成是加减乘除混合运算),有两种算法,一种是乘法优先运算,另一种是依次从左向右运算(不管它是否乘在前还是加在前). 个人赛中试着模拟 ...

  10. Alpha冲刺随笔八:第八天

    课程名称:软件工程1916|W(福州大学) 作业要求:项目Alpha冲刺(十天冲刺) 团队名称:葫芦娃队 作业目标:在十天冲刺里对每天的任务进行总结. 随笔汇总:https://www.cnblogs ...