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

前面几篇文章:

       《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

Android 4.0 ICS SystemUI浅析——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:

Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置_第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";

	@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)); 
			}
		});
	}
}
           总结:关于Clock的加载以及工作流程比较简单,但其中通过自定义view实现自动更新TextView还是值得学习。Clock的工作流程和Date的工作流程是一致的,也就是它们都是通过广播这种方式来更新内容的。

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

你可能感兴趣的:(Android 4.0 ICS SystemUI浅析——StatusBar工作流程之时间日期设置)