Helloworld项目分析杂记一

简介: 一、模块分析  AVKON大概是Symbian的一个编程框架,类似于MFC。HelloWorld项目是基于此application framework开发的。
一、模块分析  AVKON大概是Symbian的一个编程框架,类似于MFC。HelloWorld项目是基于此application framework开发的。
  首先,每个编译出来的GUI应用程序(*.app)实际上是一个dll,不是一个通常意义上的可执行模块。每个app都导出了一个函数NewApplication(),它是用序号导出的。以Helloworld工程为例,察看目录%SDKROOT%/6.1/Series60/Epoc32/BUILD/SYMBIAN/6.1/SERIES60/SERIES60EX/HELLOWORLD/GROUP/HELLOWORLD/WINS下面的HELLOWORLD.def文件可以看出这一点。NewApplication的函数体在Helloworld.cpp文件中,它所做的工作很简单,仅仅是new一个CHelloWorldApplication对象然后返回其指针。在这个文件中还有另一个全局函数E32Dll,此函数意义等同于Windows中dll编程的DllMain函数,是DLL的Entry Point,在此可以进行初始化TLS(Thread Local Storage)的动作,每个Symbian程序都必须有这个函数。当应用程序准备运行的时候,E32Dll会最先被框架所调用,框架会传进来一个参数aReason,此参数有4种可能值:EDllProcessAttach, EDllThreadAttach, EDllThreadDetach or EDllProcessDetach,在这里直接返回KErrNone,表示没有错误。
  接下来分析应用程序类CHelloWorldApplication。这个类按照官方文档的说法就是“An Application that creates the new blank document and defines the application UID”,意思就是这个类是负责new出一个空白文档,并定义应用程序的UID。这个类只有两个成员函数:AppDllUid和CreateDocumentL,分别考察之。AppDllUid仅仅返回一个预先定义写死的一个UID,CreateDocumentL函数用CHelloWorldApplication应用程序对象的this指针new出一个文档对象出来CHelloWorldDocument(注:函数名后面加L表示此函数可以异常退出)。奇怪的是这个应用程序类并没有提供构造函数和析构函数,按照C++的语意,派生类先调用父类的构造函数再调用自己的。我想,可能是因为CHelloWorldApplication类没有增加任何数据成员(仅仅多了两个函数成员),所以无需自己提供构造函数来完成额外的构造动作吧。但是追寻到其祖先类CEikApplication,却发现其构造函数是Protected的,难道它想使用类似MFC的RTTI信息动态创建对象?目前还不清楚)。
  然后是文档类CHelloWorldDocument,这个类的作用是“A Document object that represents the data model and is used to construct the App UI”,感觉有点类似于MFC中的文档类,负责表示数据,创建UI。首先映入眼帘的是构造函数/析构函数。这一对函数在这里是空函数,先不去管它。剩下的3个成员函数,NewL/NewLC和ConstructL用于完成两步构造。所谓两段构造,是Symbian里面引入的一个概念,因为C++的构造函数和析构函数如果失败,是不允许抛出异常的,如果直接把大量的初始化代码放在构造函数里的话,会使得构造函数失败的几率增加,一旦构造失败,就很难对构造过程中半途而废的“烂尾楼”进行收拾,Symbian提出的两步构造就是把所有可能导致失败的代码全部移出构造函数,放在成员函数ConstructL()里进行,在构造函数执行完毕后再调用该ConstructL完成后续构造动作,以保证构造函数绝对不会失败,这一过程称为“两步构造”。与此相关,Symbian的一些类经常添加了一对函数:NewL和NewLC,来实现两步构造,这两个函数被声明为static的,回忆C++的语法定义,static成员函数实际上是独立于类之外的,它们可以在类的任何一个实例存在之前被调用,因此Symbian中往往用显式调用这两个函数的办法来创建类的实例,我们先看一下代码:
  CHelloWorldDocument* CHelloWorldDocument::NewL(CEikApplication& aApp)
  {
  CHelloWorldDocument* self = NewLC(aApp);
  //构造过程成功,把指针从Cleanup Stack中弹出,因为已无保护必要
  CleanupStack::Pop(self);
  return self;
  }
  CHelloWorldDocument* CHelloWorldDocument::NewLC(CEikApplication& aApp)
  {
  CHelloWorldDocument* self = new (ELeave) CHelloWorldDocument(aApp); //第一步构造
  //self指向一个构造了一半的实例,将其推入Cleanup Stack,防止后续构造失败
  CleanupStack::PushL(self);
  self->ConstructL(); //第二步构造
  return self;
  }
  可以看出,NewL调用NewLC,NewLC先new出一个CHelloWorldDocument对象的实例(这是第一步构造,new已经被重载了,ELeave是它的参数,表示当new失败的时候会异常退出),然后将指针推入Cleanup Stack,紧接着再调用ConstructL(这是第二步构造),NewL和NewLC的区别是:NewL在堆上创建实例,当出现内存不足错误时,就异常退出;NewLC在堆上创建实例并将其推入到Cleanup Stack中。如果内存不足就异常退出。(注:后缀L就是Leave的意思,表示可能异常退出,C是Cleanup Stack的意思,表示会将在堆上创建的对象推入Cleanup Stack)。
  最后剩下一个函数CreateAppUiL,这个函数负责创建UI,向框架返回一个指向UI对象的指针,值得注意的是UI类的构造过程并不是两步构造,它的构造函数在CreateAppUiL中被调用后,框架得到UI对象的指针,接着框架再主动调用UI类的ConstructL函数完成UI对象的全部构造工作,UI对象的所有权也转交给框架,因此文档类并不否则销毁UI对象。
  第3个类是UI类CHelloWorldAppUi,如前所述,UI对象不是基于两步构造,没有提供NewL和NewLC函数。官方帮助中对它的描述是“An App Ui (Application User Interface) object that handles the commands generated from menu options”。可见它是专用于处理用户命令输入的。我们先分析ConstructL函数,它先调用基类的BaseConstructL()函数,完成一些诸如读取资源一类的工作;接着,用两步构造创建View类的实例(View类是负责在屏幕上进行显示的,下面会有介绍),View类由UI类拥有,在CHelloWorldAppUi类中有一个指针成员iAppView指向所构造的View对象,View类的析构在UI类的析构函数中完成;最后调用AddToStackL(iAppView)把View对象加到Control Stack上(当UI对象被销毁的时候必须把View对象从Control Stack上拿下来,参见CHelloWorldAppUi类的析构函数),这样做是为了确保应用程序能响应用户的按键动作,只要View对象在Control Stack上,无论用户什么时候按下按键,OfferKeyEventL 函数就会被调用,这个函数有两个参数分别表示按键事件的类型(Key down、Key press或者Key up)以及所按下的按键的编码。接下来要讲UI的主要任务——处理用户命令输入。这是在HandleCommandL成员函数中进行的。这个函数大体框架类似于Windows SDK编程中的窗口函数——一个大的switch结构,整体结构还是很好理解的,基本上望文知义,几个aCommand定义,比如EHelloWorldCommand1和EAknSoftkeyExit,是在Helloworld.rss(这是资源文件,有点类似于VC里的res文件)里定义的,EHelloWorldCommand1指左软键Option弹出菜单中的“Hello”菜单项,EAknSoftkeyExit指“Hello”下面的“Exit”菜单项,唯一是EEikCmdExit没有找到定义所在,可能是框架预定义的。_LIT宏定义了一个TLitC类的实例message,并初始化为第二个参数给出的串,接着new出一个CAknInformationNote对象(这个对象的作用大概有点象MessageBox),显示message中的字符串。需要特别指出的是,在最后的Default分支中有一个Panic函数,Panic的字面意思是“惊慌, 恐慌”,我的理解,panic code大概就是error code的意思,这个函数大概就是一个返回一个error code,在Helloworld.pan文件中定义了EHelloWorldBasicUi=1。
  第4个类是View类,专门用于在屏幕上显示数据的。这个类一共6个成员函数,构造函数和析构函数用于第一步构造,此处是空的,NewL和NewLC的作用如前所述,这几个老面孔就不提了。我们分析的重点在Draw函数,它类似MFC的OnPaint函数,框架在需要重绘的时候会去调用它,程序员不应该手动调用它,因为在调用Draw之前必须先激活(Activated)系统的GC(Graphics Context)——类似DC的一个概念。如果我们想重绘窗口怎么办呢?答案是使用DrawNow函数。最后一点要注意的是,Draw函数是绝不允许异常退出(Leave)的,因为前面讲过,Draw函数是程序员编写的,在程序运行过程中,有可能被框架自动调用,如果Draw函数向框架抛出异常,框架不可能未卜先知地知道发生了什么异常,又如何处理错误呢?所以Draw函数必须使用TRAP宏来主动捕获错误。
目录
相关文章
|
5月前
|
Java 关系型数据库 MySQL
太牛了! GitHub大牛呕心沥血整理的5000页Java学习手册文档
今天整理了一套 5000 页的 Java 学习手册,,新鲜出炉,分享给大家!此手册内容专注 Java技术,包括 JavaWeb,SSM,Linux,Spring Boot,MyBatis,MySQL,Nginx,Git,GitHub,Servlet,IDEA,多线程,集合,JVM,DeBug, Dubbo,Redis,算法,面试题等相关内容。
|
10月前
|
数据可视化 Java
中南林业科技大学Java实验报告十二:数据库系统设计 - 从0到1搭建java可视化学生管理系统源代码(二)
中南林业科技大学Java实验报告十二:数据库系统设计 - 从0到1搭建java可视化学生管理系统源代码
101 0
|
6月前
|
消息中间件 设计模式 分布式计算
大厂招聘重点全在这!GitHub置顶Java基础-高级面试库+自学路线
最近几年经常会听见这样一种声音:“程序员是吃青春饭的,年龄一大就不吃香了”,在当下这种互联网产业增速放缓,甚至隐约展现出疲态的时刻,此类言论就很有市场。
|
8月前
|
设计模式 Dubbo Java
让GitHub低头认错的这份阿里内部绝密Java面试八股文手册有多强?
今天给大家分享出一份让大家上班摸鱼也可以随意看的阿里巴巴内部特供Java面试八股文手册,这份手册据说曾经也是让GitHub都为之低头的存在! 正所谓“旧时王谢堂前燕,飞入寻常百姓家”希望大家看完这份手册都可以拿上自己满意的offer!
|
9月前
|
算法 Java 数据库
Alibaba官方最新发布的这份Java学习导图+彩版手册,真不是吹的
最近一直有小伙伴催小编更新一份有关于Java快速学习捷径的资料,小编想说“书山有路勤为径”,从古至今这句话大家都应该懂的! 不过为了小伙伴能更好的学习,小编特意给大家整理了一份比较详细的Java学习路线和《Java核心知识点总结》一书在手天下我有!
84 1
|
10月前
|
存储 消息中间件 缓存
史上最全最详细的Java架构师成长路径图,程序员必备
从新手码农到高级架构师,要经过几步?要多努力,才能成为为人倚重的技术专家?本文将为你带来一张程序员发展路径图,但你需要知道的是,天下没有普适的道理,具体问题还需具体分析,实践才能出真知。
983 0
|
10月前
|
消息中间件 算法 架构师
不愧是Github疯传的腾讯Java进阶笔记,总结太全了
移动互联网时代,IT 系统变得愈加复杂,对我们程序员的要求也是越来越高,技术不断更新,我们还不能停止学习,停下来了就会被打上一个‘不合格的程序员’的标签,如何成为一位「不那么差」的程序员?「不那么差」的程序员又需要掌握一些什么知识呢?这篇文章就与大家聊一聊这个话题。 以下内容仅代表我从业以来所积累的相关经验,不对不全的地方还请大家海涵,下面我会从硬技能、软实力这些方面尽量阐述我所认为的 “不那么差的程序员” 应当做到哪些技能。
|
10月前
|
Java 数据安全/隐私保护 索引
Java实训项目一一拼图游戏(附源码)
Java实训项目一一拼图游戏(附源码)
193 1
|
10月前
|
SQL 存储 Java
Java实训项目一一考试系统(附源码)
Java实训项目一一考试系统(附源码)
172 0
|
10月前
|
数据可视化 druid 前端开发
中南林业科技大学Java实验报告十二:数据库系统设计 - 从0到1搭建java可视化学生管理系统源代码(一)
中南林业科技大学Java实验报告十二:数据库系统设计 - 从0到1搭建java可视化学生管理系统源代码
110 0