前面几篇文章:
《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"
- />
- 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>
- public class UpdateActivity extends Activity{
- private ClockView mDateView;
- private Button mButton;
- public static final String ACTION = "com.seven.update";
- @Override
- protected 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() {
- @Override
- public void onClick(View v) {
- sendBroadcast(new Intent(ACTION));
- }
- });
- }
- }
本文涉及到的代码以及图片资源下载请点击这里!