Android 4.0日历(calendar)源码分析之概览

Calendar

从4.0开始,谷歌android系统有了脱碳换骨的改变,相应的日历应用的代码架构也跟2.*完全不同。代码更规范,当然也更复杂,且涉及到了android开发的方方面面。

如果你熟悉了ics(4.0)版本的日历代码,你应该也是一个应用层高手了。4.0以上的版本日历做了相应的改进,但是代码架构没变,且改动也不大。而且我猜测未来的6个版本之类日历的架构都不会再变了。

这里要说明的是将谷歌在git的日历代码导入在eclipse里可能编译不了,因为一般的sdk中,没有日历需要的几个包,譬如:com.android.calendarcommon 而我发现sdk的source中,是有这个包的,只是并没有打包成lib,个中原因,还请赐教。本人是初学者,也许能细心的研究日历,而未必有顾览全局的知识,有时候难免会贻笑大方。还有就是日历代码其实是分为两个部分,provider和日历本身,日历的provider代码不在Calendar中,是一个独立的apk,可见google对日历的重视程度。关于provider我就不去分析了,因为修改它的时候很少,且有风险。

为了避免张冠李戴,我们来看看4.0日历的截图,我看到网上基本都是2.3版本的日历,或者是其他山寨日历。

日历分为四个视图

月视图                                 周视图

日视图                                 日程视图

这四个视图在整个应用中属于同一级别都是顶级视图。

关于代码,我们先来看看日历代码的目录结构,看清楚,这才是4.0的日历代码。

刚刚介绍界面的时候讲到了四个视图,其实在代码模块中基本是能找到与之相对应的文件的。上面的代码结构中,你可能会很直观的看到月视图以及日程对应的代码,agendamonth目录,但是日视图和周视图去哪里了呢?

周视图和日视图,在源码的最上层,DayView.Java文件中,当然还有些相关的文件。

如果你对文字比较敏感,你可能会发现一个命名很有特点的java文件,AllInOneActivity.java,第一次看到这个命名的时候,我着实笑了一阵子,这是不是有点不负责啊。这个AllInOneActivity真的很重要,所有视图其实都是需要这个AllInOneActivity的,视图之间的差别体现在各自的fragment中。AllInOneActivity相当于一个派发者。

AllInOneActivity中定义了actionbar的布局样式以及菜单项目,初始化了各种视图所需要的Fragment,定义了各种菜单以及按钮的响应事件处理方式(比如menu菜单),以及事件处理机制handleEvent。而且从AllInOneActivity中我们还知道,ics的日历代码其实是同时针对平板和手机两种设备的,以后如果没有做说明,我们讨论的都是手机部分的代码,其实专门针对平板的代码也不多。

在下一篇文章中我们将对AllInOneActivity进行代码层面的分析。

我们觉得可以对日历的代码进行这样的归类:

  1. 处理各种视图的模块,包括月、周、日、日程各种fragment为入口,比如月视图以/month/MonthByWeekFragment.java为入口。周视图、日视图以/DayFragment.java为入口,日程以/agenda/AgendaFragment.java为入口。

  2. 设置模块/CalendarSettingsActivity.java为入口

  3. 日程编辑和新建部分,/event/EditEventFragment.java为入口。

  4. 单条日程信息的显示部分/EventInfoActivity.java为入口。

  5. Alerts日程消息通知部分/alert/AlertActivity.java为入口。

而日历代码中被反复调用的最频繁的是如下的几个文件:

Utils.java 

工具函数,具体日期的数字显示值的获取就是通过它,各个账户颜色的取值也是通过它,公历的一些转换也是它。

CalendarController.java

CalendarController从字面上来理解应该叫做控制器,我们知道日历的很多事件响应都是在AllInOneActivity中发生的,但是我们的处理却不是在这里,而是在响应的视图对应的activity或者fragment之中,如何让捕获到事件的AllInOneActivity去通知相应的fragment去处理这些事件呢,就是通过CalendarController 。CalendarController相当于一个中转站。CalendarController中定义了一个叫EventHandler的接口:

public interface EventHandler {

long getSupportedEventTypes();

void handleEvent(EventInfo event);

/**

  • This notifies the handler that the database has changed and it should

  • update its view.

*/

void eventsChanged();

}

AllInOneActivity本身继承了EventHandler并实现了handleEvent方法,同时各个fragment也继承了继承了EventHandler并实现了handleEvent方法,这样就能在CalendarController随意的调用各个模块。

AllInOneActivity中的handleEvent具有优先处理的特权,我将能处理时间的对象成为事件处理对象,这些东西我将在CalendarController里面详细的讲解。

在今后的文章中我们将详细的讲解CalendarController。

视图之外

   除了四个视图之外,日历还有独立的几个部分,比如设置界面,新建日程界面、显示账号的界面、查看日程详情的界面。这几个部分我们最后讨论,因为他几乎没有涉及到日历的架构问题。

   最后,关于日历的分析我会以AllInOneactivity开始。