前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android学习笔记(九)一个例子弄清Service与Activity通信

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

作者头像
codingblock
发布2017-12-29 15:08:32
2.1K0
发布2017-12-29 15:08:32
举报
文章被收录于专栏:CodingBlockCodingBlock

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

  本篇将写一个demo来说明以下三个问题:

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

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

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

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

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

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

一、准备Service

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

代码语言:javascript
复制
 1 public class MyService extends Service {
 2     private String data = "默认消息";
 3     private boolean serviceRunning = false;
 4     
 5     // 必须实现的方法,用于返回Binder对象
 6     @Override
 7     public IBinder onBind(Intent intent) {
 8         System.out.println("--onBind()--");
 9         return new MyBinder();
10     }
11 
12     public class MyBinder extends Binder {
13         MyService getService() {
14             return MyService.this;
15         }
16 
17         public void setData(String data) {
18             MyService.this.data = data;
19         }
20     }
21 
22     // 创建Service时调用该方法,只调用一次
23     @Override
24     public void onCreate() {
25         super.onCreate();
26         System.out.println("--onCreate()--");
27         serviceRunning = true;
28         new Thread() {
29             @Override
30             public void run() {
31                 int n = 0;
32                 while (serviceRunning) {
33                     n++;
34                     String str = n + data;
35                     System.out.println(str);
36                     if (dataCallback != null) {
37                         dataCallback.dataChanged(str);
38                     }
39                     try {
40                         sleep(1000);
41                     } catch (InterruptedException e) {
42                         e.printStackTrace();
43                     }
44                 }
45             };
46         }.start();
47     }
48 
49     // 每次启动Servcie时都会调用该方法
50     @Override
51     public int onStartCommand(Intent intent, int flags, int startId) {
52         System.out.println("--onStartCommand()--");
53         data = intent.getStringExtra("data");
54         return super.onStartCommand(intent, flags, startId);
55     }
56 
57     // 解绑Servcie调用该方法
58     @Override
59     public boolean onUnbind(Intent intent) {
60         System.out.println("--onUnbind()--");
61         return super.onUnbind(intent);
62     }
63 
64     // 退出或者销毁时调用该方法
65     @Override
66     public void onDestroy() {
67         serviceRunning = false;
68         System.out.println("--onDestroy()--");
69         super.onDestroy();
70     }
71 
72     DataCallback dataCallback = null;
73 
74     public DataCallback getDataCallback() {
75         return dataCallback;
76     }
77 
78     public void setDataCallback(DataCallback dataCallback) {
79         this.dataCallback = dataCallback;
80     }
81 
82     // 通过回调机制,将Service内部的变化传递到外部
83     public interface DataCallback {
84         void dataChanged(String str);
85     }
86 
87 }

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

二、准备布局文件

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

代码语言:javascript
复制
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical">
 6 
 7     <TextView
 8         android:id="@+id/tv_out"
 9         android:layout_width="fill_parent"
10         android:layout_height="wrap_content"
11         android:text="显示区域" />
12     
13     <EditText
14         android:id="@+id/et_data"
15         android:layout_width="match_parent"
16         android:layout_height="wrap_content"
17         android:ems="10" >
18 
19         <requestFocus />
20     </EditText>
21     
22     <Button
23         android:id="@+id/btn_start_service"
24         android:layout_width="fill_parent"
25         android:layout_height="wrap_content"
26         android:text="startService" />
27     
28     <Button
29         android:id="@+id/btn_stop_service"
30         android:layout_width="fill_parent"
31         android:layout_height="wrap_content"
32         android:text="stopService" />
33     
34     <Button
35         android:id="@+id/btn_bind_service"
36         android:layout_width="fill_parent"
37         android:layout_height="wrap_content"
38         android:text="bindService" />
39     
40     <Button
41         android:id="@+id/btn_unbind_service"
42         android:layout_width="fill_parent"
43         android:layout_height="wrap_content"
44         android:text="unbindService" />
45     
46     <Button
47         android:id="@+id/btn_sync_data"
48         android:layout_width="fill_parent"
49         android:layout_height="wrap_content"
50         android:text="同步数据" />
51 
52 </LinearLayout>

三、准备Activity

   MainActivity代码如下:

代码语言:javascript
复制
  1 public class MainActivity extends Activity implements OnClickListener {
  2 
  3     private Intent intent = null;
  4     private Button btn_start_service;
  5     private Button btn_stop_service;
  6     private Button btn_bind_service;
  7     private Button btn_unbind_service;
  8     private Button btn_sync_data;
  9     private EditText et_data;
 10     private TextView tv_out;
 11     MyServiceConn myServiceConn;
 12     MyService.MyBinder binder = null;
 13 
 14     @Override
 15     protected void onCreate(Bundle savedInstanceState) {
 16         super.onCreate(savedInstanceState);
 17         setContentView(R.layout.activity_main);
 18         intent = new Intent(this, MyService.class);
 19         myServiceConn = new MyServiceConn();
 20         setOnClick();
 21     }
 22     
 23     @Override
 24     public void onClick(View v) {
 25         switch (v.getId()) {
 26         case R.id.btn_start_service:
 27             //用intent启动Service并传值
 28             intent.putExtra("data", et_data.getText().toString());
 29             startService(intent);
 30             break;
 31         case R.id.btn_stop_service:
 32             //停止Service
 33             stopService(intent);
 34             break;
 35         case R.id.btn_bind_service:
 36             //绑定Service
 37             bindService(intent, myServiceConn, Context.BIND_AUTO_CREATE);
 38             break;
 39         case R.id.btn_unbind_service:
 40             //解绑Service
 41             if (binder != null) {
 42                 unbindService(myServiceConn);
 43             }
 44             break;
 45         case R.id.btn_sync_data:
 46             //注意:需要先绑定,才能同步数据
 47             if (binder != null) {
 48                 binder.setData(et_data.getText().toString());
 49             }
 50             break;
 51         default:
 52             break;
 53         }
 54     }
 55 
 56     class MyServiceConn implements ServiceConnection {
 57         // 服务被绑定成功之后执行
 58         @Override
 59         public void onServiceConnected(ComponentName name, IBinder service) {
 60             // IBinder service为onBind方法返回的Service实例
 61             binder = (MyService.MyBinder) service;
 62             binder.getService().setDataCallback(new MyService.DataCallback() {
 63                 //执行回调函数
 64                 @Override
 65                 public void dataChanged(String str) {
 66                     Message msg = new Message();
 67                     Bundle bundle = new Bundle();
 68                     bundle.putString("str", str);
 69                     msg.setData(bundle);
 70                     //发送通知
 71                     handler.sendMessage(msg);
 72                 }
 73             });
 74         }
 75 
 76         @SuppressLint("HandlerLeak") 
 77         Handler handler = new Handler() {
 78             public void handleMessage(android.os.Message msg) {
 79                 //在handler中更新UI
 80                 tv_out.setText(msg.getData().getString("str"));
 81             };
 82         };
 83 
 84         // 服务奔溃或者被杀掉执行
 85         @Override
 86         public void onServiceDisconnected(ComponentName name) {
 87             binder = null;
 88         }
 89     }
 90     
 91     private void loadUI() {
 92         btn_start_service = (Button) findViewById(R.id.btn_start_service);
 93         btn_stop_service = (Button) findViewById(R.id.btn_stop_service);
 94         btn_bind_service = (Button) findViewById(R.id.btn_bind_service);
 95         btn_unbind_service = (Button) findViewById(R.id.btn_unbind_service);
 96         btn_sync_data = (Button) findViewById(R.id.btn_sync_data);
 97         et_data = (EditText) findViewById(R.id.et_data);
 98         tv_out = (TextView) findViewById(R.id.tv_out);
 99     }
100 
101     private void setOnClick() {
102         loadUI();
103         btn_start_service.setOnClickListener(this);
104         btn_stop_service.setOnClickListener(this);
105         btn_bind_service.setOnClickListener(this);
106         btn_unbind_service.setOnClickListener(this);
107         btn_sync_data.setOnClickListener(this);
108     }
109 
110 }

   代码分析:

  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、改变输入框内容,点击同步数据,界面和对应的日志如下:

  因本人水平有限,如在文中发现错误或者描述不当的地方,敬请指正,感激不尽!

  声明:欢迎转载,转载是请注明本文链接,谢谢!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-09-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档