歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android應用實例之計時器之通過Service&BroadcastReceiver實現UI動態更新

Android應用實例之計時器之通過Service&BroadcastReceiver實現UI動態更新

日期:2017/3/1 11:16:17   编辑:Linux編程

實現的功能:計時器。

實現的思路: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. import android.app.Activity;
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.IntentFilter;
  7. import android.graphics.Color;
  8. import android.os.Bundle;
  9. import android.widget.TextView;
  10. public class DynamicUIActivity extends Activity {
  11. public static String TIME_CHANGED_ACTION = "com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION";
  12. public static TextView time = null;
  13. private Intent timeService = null;
  14. @Override
  15. public void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.main);
  18. //初始化UI
  19. initUI();
  20. System.out.println("initUI");
  21. //注冊廣播-方法1
  22. /*
  23. * 配置
  24. * <receiver android:name=".UITimeReceiver">
  25. <intent-filter>
  26. <action android:name="com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION"/>
  27. </intent-filter>
  28. </receiver>
  29. */
  30. //注冊廣播-方法2
  31. //注冊廣播,監聽後台Service發送過來的廣播
  32. //registerBroadcastReceiver();
  33. //啟動服務,時間改變後發送廣播,通知UI層修改時間
  34. startTimeService();
  35. }
  36. public TextView getTimeTextView(){
  37. return time;
  38. }
  39. /**
  40. * 初始化UI
  41. */
  42. private void initUI(){
  43. time = (TextView)findViewById(R.id.time);
  44. time.setTextColor(Color.RED);
  45. time.setTextSize(15);
  46. }
  47. /**
  48. * 注冊廣播
  49. */
  50. private void registerBroadcastReceiver(){
  51. UITimeReceiver receiver = new UITimeReceiver();
  52. IntentFilter filter = new IntentFilter(TIME_CHANGED_ACTION);
  53. registerReceiver(receiver, filter);
  54. }
  55. /**
  56. * 啟動服務
  57. */
  58. private void startTimeService(){
  59. timeService = new Intent(this,TimeService.class);
  60. this.startService(timeService);
  61. }
  62. @Override
  63. protected void onDestroy() {
  64. super.onDestroy();
  65. //停止服務
  66. stopService(timeService);
  67. }
  68. }

第二步:實現自定義BroadcatReceiver類UITimeReceiver,負責接收從後台Service發送過來的廣播,獲取最新時間數據後更新UI層組件。本類最好作為UI層(Activity)的內部類,此處將其作為外部類實現(通過xml文件配置注冊BroadcatReceiver,如果是內部類如何通過xml文件配置目前沒找到),有意顯示如此做導致代碼不夠優雅。

UITimeReceiver代碼如下:

  1. package com.zyg.demo.service.dynamicui;
  2. import android.content.BroadcastReceiver;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. /**
  7. * 自定義的UI層BroadcastReceiver,負責監聽從後台Service發送過來的廣播,根據廣播數據更新UI
  8. * @author zhangyg
  9. */
  10. public class UITimeReceiver extends BroadcastReceiver{
  11. private DynamicUIActivity dUIActivity = new DynamicUIActivity();
  12. @Override
  13. public void onReceive(Context context, Intent intent) {
  14. String action = intent.getAction();
  15. if(DynamicUIActivity.TIME_CHANGED_ACTION.equals(action)){
  16. Bundle bundle = intent.getExtras();
  17. String strtime = bundle.getString("time");
  18. //此處實現不夠優雅,為了在UITimeReceiver中使用DynamicUIActivity中的TextView組件time,而將其設置為public類型,
  19. //更好的實現是將UITimeReceiver作為DynamicUIActivity的內部類
  20. dUIActivity.time.setText(strtime);
  21. }
  22. }
  23. }

第三步:實現自定義Service類TimeService,其代碼如下:

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

第四步:修改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. <application android:icon="@drawable/icon" android:label="@string/app_name">
  8. <activity android:name=".DynamicUIActivity"
  9. android:label="@string/app_name">
  10. <intent-filter>
  11. <action android:name="android.intent.action.MAIN" />
  12. <category android:name="android.intent.category.LAUNCHER" />
  13. </intent-filter>
  14. </activity>
  15. <receiver android:name=".UITimeReceiver">
  16. <intent-filter>
  17. <action android:name="com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION"/>
  18. </intent-filter>
  19. </receiver>
  20. <service android:name=".TimeService"></service>
  21. </application>
  22. </manifest>

第五步:運行程序,效果如下:

Copyright © Linux教程網 All Rights Reserved