Android应用实例之计时器之通过Service&BroadcastReceiver实现UI动态更新

2020年1月31日05:31:58
评论

实现的功能:计时器。

实现的思路:1)后台Service每隔1秒发送广播通知时间已发生变化;

               2)UI层(Activity)通过BroadcastReceiver接收到广播,更新显

                      示的时间。

关键技术点:Service的应用、BroadcastReceiver的应用

说明:1)Activity与通过startService方法启动的Service之间无法直接进行通信,但是借助BroadcastService可以实现两者之间的通信。

2)实现计时器的方式有很多种,比如通过Thread的sleep等,此处只是演示Service与BroadcastService的组合应用(可以将Service中获取当前时间的操作想象为非常耗时的操作,所以不宜直接在UI层来做)。

3)此处演示的Service与BroadcastService的组合是“单向通信”即:UI层只是被动接收Service发来的广播,而没有主  动发送广播控制后台Service。下一篇文章将会编写一个实例进行演示“双向通信”。

第一步:新建一个工程,命名为DynamicUI,Activity命名为DynamicUIActivity。

修改布局文件main.xml,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:Android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent" android:background="#FFFFFF">  
  5.     <TextView android:id="@+id/tv" android:layout_width="wrap_content"  
  6.         android:layout_height="wrap_content" android:text="当前时间: " />  
  7.     <TextView android:id="@+id/time" android:layout_width="fill_parent"  
  8.         android:layout_height="wrap_content"  
  9.         android:layout_toRightOf="@id/tv" />  
  10. </RelativeLayout>  

DynamicUIActivity类代码如下:

  1. package com.zyg.demo.service.dynamicui;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.graphics.Color;  
  9. import android.os.Bundle;  
  10. import android.widget.TextView;  
  11.   
  12. public class DynamicUIActivity extends Activity {  
  13.     public static String TIME_CHANGED_ACTION = "com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION";  
  14.     public static TextView time = null;  
  15.     private Intent timeService = null;  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.           
  21.         //初始化UI   
  22.         initUI();  
  23.         System.out.println("initUI");  
  24.           
  25.         //注册广播-方法1   
  26.         /* 
  27.          * 配置 
  28.          * <receiver android:name=".UITimeReceiver"> 
  29.             <intent-filter> 
  30.                 <action android:name="com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION"/> 
  31.             </intent-filter> 
  32.         </receiver> 
  33.          */  
  34.           
  35.         //注册广播-方法2   
  36.         //注册广播,监听后台Service发送过来的广播   
  37.         //registerBroadcastReceiver();   
  38.           
  39.         //启动服务,时间改变后发送广播,通知UI层修改时间   
  40.         startTimeService();  
  41.     }  
  42.       
  43.     public TextView getTimeTextView(){  
  44.         return time;  
  45.     }  
  46.       
  47.     /** 
  48.      * 初始化UI 
  49.      */  
  50.     private void initUI(){  
  51.         time = (TextView)findViewById(R.id.time);  
  52.         time.setTextColor(Color.RED);  
  53.         time.setTextSize(15);  
  54.     }  
  55.       
  56.     /** 
  57.      * 注册广播 
  58.      */  
  59.     private void registerBroadcastReceiver(){  
  60.         UITimeReceiver receiver = new UITimeReceiver();  
  61.         IntentFilter filter = new IntentFilter(TIME_CHANGED_ACTION);  
  62.         registerReceiver(receiver, filter);  
  63.     }  
  64.       
  65.     /** 
  66.      * 启动服务 
  67.      */  
  68.     private void startTimeService(){  
  69.         timeService = new Intent(this,TimeService.class);  
  70.         this.startService(timeService);  
  71.     }  
  72.       
  73.     @Override  
  74.     protected void onDestroy() {  
  75.         super.onDestroy();  
  76.         //停止服务   
  77.         stopService(timeService);  
  78.     }  
  79. }  

第二步:实现自定义BroadcatReceiver类UITimeReceiver,负责接收从后台Service发送过来的广播,获取最新时间数据后更新UI层组件。本类最好作为UI层(Activity)的内部类,此处将其作为外部类实现(通过xml文件配置注册BroadcatReceiver,如果是内部类如何通过xml文件配置目前没找到),有意显示如此做导致代码不够优雅。

UITimeReceiver代码如下:

  1. package com.zyg.demo.service.dynamicui;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.os.Bundle;  
  7.   
  8. /** 
  9.  * 自定义的UI层BroadcastReceiver,负责监听从后台Service发送过来的广播,根据广播数据更新UI 
  10.  * @author zhangyg 
  11.  */  
  12. public class UITimeReceiver extends BroadcastReceiver{  
  13.     private DynamicUIActivity dUIActivity = new DynamicUIActivity();  
  14.     @Override  
  15.     public void onReceive(Context context, Intent intent) {  
  16.         String action = intent.getAction();  
  17.         if(DynamicUIActivity.TIME_CHANGED_ACTION.equals(action)){  
  18.             Bundle bundle = intent.getExtras();  
  19.             String strtime = bundle.getString("time");  
  20.             //此处实现不够优雅,为了在UITimeReceiver中使用DynamicUIActivity中的TextView组件time,而将其设置为public类型,   
  21.             //更好的实现是将UITimeReceiver作为DynamicUIActivity的内部类   
  22.             dUIActivity.time.setText(strtime);  
  23.         }  
  24.     }  
  25. }  

第三步:实现自定义Service类TimeService,其代码如下:

  1. package com.zyg.demo.service.dynamicui;  
  2.   
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Date;  
  5. import java.util.Timer;  
  6. import java.util.TimerTask;  
  7.   
  8. import android.app.Service;  
  9. import android.content.ComponentName;  
  10. import android.content.Intent;  
  11. import android.os.Bundle;  
  12. import android.os.IBinder;  
  13. import android.util.Log;  
  14.   
  15. public class TimeService extends Service{  
  16.     private String TAG = "TimeService";  
  17.     private Timer timer = null;  
  18.     private SimpleDateFormat sdf = null;  
  19.     private Intent timeIntent = null;  
  20.     private Bundle bundle = null;  
  21.     @Override  
  22.     public void onCreate() {  
  23.         super.onCreate();  
  24.         Log.i(TAG,"TimeService->onCreate");  
  25.         //初始化   
  26.         this.init();  
  27.         //定时器发送广播   
  28.         timer.schedule(new TimerTask() {  
  29.             @Override  
  30.             public void run() {  
  31.                 //发送广播   
  32.                 sendTimeChangedBroadcast();  
  33.             }  
  34.         }, 1000,1000);  
  35.     }  
  36.       
  37.     @Override  
  38.     public IBinder onBind(Intent intent) {  
  39.         Log.i(TAG,"TimeService->onBind");  
  40.         return null;  
  41.     }  
  42.       
  43.     /** 
  44.      * 相关变量初始化 
  45.      */  
  46.     private void init(){  
  47.         timer = new Timer();  
  48.         sdf = new SimpleDateFormat("yyyy年MM月dd日 "+"hh:mm:ss");  
  49.         timeIntent = new Intent();  
  50.         bundle = new Bundle();  
  51.     }  
  52.       
  53.     /** 
  54.      * 发送广播,通知UI层时间已改变 
  55.      */  
  56.     private void sendTimeChangedBroadcast(){  
  57.         bundle.putString("time", getTime());  
  58.         timeIntent.putExtras(bundle);  
  59.         timeIntent.setAction(DynamicUIActivity.TIME_CHANGED_ACTION);  
  60.         //发送广播,通知UI层时间改变了   
  61.         sendBroadcast(timeIntent);  
  62.     }  
  63.       
  64.     /** 
  65.      * 获取最新系统时间 
  66.      * @return 
  67.      */  
  68.     private String getTime(){  
  69.         return sdf.format(new Date());  
  70.     }  
  71.       
  72.     @Override  
  73.     public ComponentName startService(Intent service) {  
  74.         Log.i(TAG,"TimeService->startService");  
  75.         return super.startService(service);  
  76.     }  
  77.       
  78.     @Override  
  79.     public void onDestroy() {  
  80.         super.onDestroy();  
  81.         Log.i(TAG,"TimeService->onDestroy");  
  82.     }  
  83. }  

第四步:修改AndroidManifest.xml文件,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="com.zyg.demo.service.dynamicui"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <uses-sdk android:minSdkVersion="8" />  
  7.   
  8.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  9.         <activity android:name=".DynamicUIActivity"  
  10.                   android:label="@string/app_name">  
  11.             <intent-filter>  
  12.                 <action android:name="android.intent.action.MAIN" />  
  13.                 <category android:name="android.intent.category.LAUNCHER" />  
  14.             </intent-filter>  
  15.         </activity>  
  16.         <receiver android:name=".UITimeReceiver">  
  17.             <intent-filter>  
  18.                 <action android:name="com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION"/>  
  19.             </intent-filter>  
  20.         </receiver>  
  21.         <service android:name=".TimeService"></service>  
  22.     </application>  
  23. </manifest>  

企鹅博客
  • 本文由 发表于 2020年1月31日05:31:58
  • 转载请务必保留本文链接:https://www.qieseo.com/171875.html

发表评论