Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置

来源:互联网 发布:淘宝怎么投诉未生产 编辑:程序博客网 时间:2024/05/22 01:51

前面几篇文章:

       《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的工作流程是一致的,也就是它们都是通过广播这种方式来更新内容的。

       本文涉及到的代码以及图片资源下载请点击这里!

原创粉丝点击