前面幾篇文章:
《Android 4.0 ICS SystemUI淺析——SystemUI啟動流程》
《Android 4.0 ICS SystemUI淺析——StatusBar結構分析》
《Android 4.0 ICS SystemUI淺析——StatusBar載入流程分析》
《Android 4.0 ICS SystemUI淺析——StatusBar載入流程之Notification》
本文主要分析StatusBar上的Clock以及Date載入以及工作流程,這算是比較簡單的了,不過它們的實現還是值得一探究竟的,那麼果斷開始吧!
註:本文來自:http://blog.csdn.net/yihongyuelan 歡迎轉載 請務必註明出處!
首先還是看看我們前面文章有提到的StatusBar組成結構圖,1
圖1
首先我們先找到SourceCode/framework/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java中的start()方法,至於為什麼要找到這裡,我們在前面的文章已有敘述,代碼如下:
public void start() { // 因為我們前面已經分析過start方法,因此這裡就不重複了,有興趣的朋友請翻看前面的文章,這裡主要引出Clock的初始化. ... ... // 這雷根據switches[0]的值,決定知否載入Clock disable(switches[0]); setSystemUiVisibility(switches[1]); topAppWindowChanged(switches[2] != 0); // StatusBarManagerService has a back up of IME token and it's restored here. setImeWindowStatus(binders.get(0), switches[3], switches[4]); setHardKeyboardStatus(switches[5] != 0, switches[6] != 0); ... ... mDoNotDisturb = new DoNotDisturb(mContext); }
根據這裡的disable(),通過Open Implementation跳轉到PhoneStatusBar中的disable方法,代碼如下:
/** * State is one or more of the DISABLE constants from StatusBarManager. */ public void disable(int state) { final int old = mDisabled; final int diff = state ^ old; mDisabled = state; ... ... if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) { boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0; // 根據show的值(true/false)是否顯示Clcok showClock(show); } ... ... } }
因為我們只關心Clock,因此其餘部分代碼在這裡就省略了。繼續跟蹤showClock方法,代碼如下:
public void showClock(boolean show) { // 這裡就完成了clock的初始化了 這裡的mStatusBarView實際上就是圖1中的id/icons。可以通過查看mStatusBarView初始化知道。 View clock = mStatusBarView.findViewById(R.id.clock); if (clock != null) { clock.setVisibility(show ? View.VISIBLE : View.GONE); } }
初始化既然完成了,那麼Clock是如何工作的呢?這就不得不找到Clock的實現了,那麼該如何尋找呢?首先,找到clock的在id/icons中的布局檔案,根據前文我們可以知道是msim_status_bar.xml,在其中可以看到:
<com.android.systemui.statusbar.policy.Clock android:id="@+id/clock" android:textAppearance="@style/TextAppearance.StatusBar.Clock" android:layout_width="wrap_content" android:layout_height="match_parent" android:singleLine="true" android:paddingRight="6dip" android:gravity="center_vertical|left" />
我們可以看到clock是一個自訂View,以此我們可以找到其具體實現在:SourceCode/framework/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java中,代碼如下:
public class Clock extends TextView { ... ... @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (!mAttached) { mAttached = true; IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_TIME_TICK); filter.addAction(Intent.ACTION_TIME_CHANGED); filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); getContext().registerReceiver(mIntentReceiver, filter, null, getHandler()); } updateClock(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mAttached) { getContext().unregisterReceiver(mIntentReceiver); mAttached = false; } } private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) { String tz = intent.getStringExtra("time-zone"); mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz)); if (mClockFormat != null) { mClockFormat.setTimeZone(mCalendar.getTimeZone()); } } updateClock(); } }; final void updateClock() { mCalendar.setTimeInMillis(System.currentTimeMillis()); setText(getSmallTime()); } ... ... }}
通過以上代碼(省略了部分代碼),我們可以看到,Clock實際上繼承自TextView,TextView的內容更新需要SetText。因此這裡通過廣播的方式來實現了這一過程,更新Clock主要由方法updateClock()來完成,觸發條件為接收到相應的廣播。Clock的更新流程了:
1.Clock類繼承TextView;
2.在初始化StatusBar時同時也註冊了Clock中的廣播;
3.Clock中的廣播等待接收並執行更新時間;
通過以上方法,實際上就實現了一個可以自動更新內容的TextView。
下面我將通過一個Demo來簡單的類比這個過程,Demo內容:通過點擊按鈕觸發廣播,廣播接收器在自訂TextView中,在該TextView中完成內容的更新。效果2:
圖2
貼出實現代碼,如下:
public final class ClockView extends TextView {private boolean update = false; public Context mContext; //調用Activity中的ACTION要一致 public static final String ACTION = "com.seven.update"; private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION.equals(action)) { updateClock(); } } }; public ClockView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; setUpdates(); } //更新介面內容 private final void updateClock() { if(update){ update = false; setText("11:15 AM"); }else {update = true;setText("22:22 PM");} } //註冊廣播接收private void setUpdates() {IntentFilter filter = new IntentFilter();filter.addAction(ACTION);mContext.registerReceiver(mIntentReceiver, filter);}}
布局檔案如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/name" /> <com.seven.viewTest.ClockView android:id="@+id/myCV" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#00ff00" android:textSize="30dip" android:text="@string/content" /> <Button android:id="@+id/myBtn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/send" /></LinearLayout>
調用Activity代碼如下:
public class UpdateActivity extends Activity{private ClockView mDateView;private Button mButton;public static final String ACTION = "com.seven.update";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.main);mDateView = (ClockView) findViewById(R.id.myCV);mButton = (Button) findViewById(R.id.myBtn);mButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {sendBroadcast(new Intent(ACTION)); }});}}
總結:關於Clock的載入以及工作流程比較簡單,但其中通過自訂view實現自動更新TextView還是值得學習。Clock的工作流程和Date的工作流程是一致的,也就是它們都是通過廣播這種方式來更新內容的。
本文涉及到的代碼以及圖片資源下載請點擊這裡!