自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Titanium架構(gòu)分析

移動開發(fā)
Titanium是一個Web應(yīng)用程序運行環(huán)境,它支持不同的系統(tǒng)平臺(Windows、Linux、Mac),并且支持Web應(yīng)用程序?qū)Ρ镜谹PIs的訪問。在基于Titanium平臺上,用戶可以快速開發(fā)和方便的部署應(yīng)用程序,并且這些應(yīng)用程序可以使用本地APIs實現(xiàn)許多普通Web應(yīng)用程序無法完成的功能和特性。

一、分析的目標(biāo)

  • 了解Titanium產(chǎn)品的基本框架結(jié)構(gòu)和特點
  • 了解Titanium產(chǎn)品如何擴展本地API以及訪問方式
  • 了解Titanium產(chǎn)品中的動態(tài)語言之間如何相互調(diào)用

二、Titanium概述

2.1 Titanium介紹

Titanium是一個Web應(yīng)用程序運行環(huán)境,它支持不同的系統(tǒng)平臺(Windows、Linux、Mac),并且支持Web應(yīng)用程序?qū)Ρ镜谹PIs的訪問。在基于Titanium平臺上,用戶可以快速開發(fā)和方便的部署應(yīng)用程序,并且這些應(yīng)用程序可以使用本地APIs實現(xiàn)許多普通Web應(yīng)用程序無法完成的功能和特性。

2.2 Titanium特點

Titanium框架具有如下幾個方面的特點:

  • 支持多平臺(Linux、Mac、Windows、移動設(shè)備)
  • 使用Web技術(shù)加快軟件開發(fā)速度
  • 支持Web中內(nèi)嵌多種編程語言
  • 支持對本地APIs的訪問
  • 通過Appcelerator網(wǎng)絡(luò)云服務(wù),基于Titanium的應(yīng)用可以更容易的打包、測試和部署
  • 本地功能的模塊化,可動態(tài)加載指定的功能模塊
  • 強大靈活的語言擴展,用戶在Titanium框架中可以很方便的擴展多種動態(tài)語言

2.3 Titanium 框架結(jié)構(gòu)

上圖來自于Appcelerator官網(wǎng),該圖以iPhone和Android兩個移動平臺為例,描述了Titanium的總體框架結(jié)構(gòu)。在Titanium框架中,Web應(yīng)用程序可以很方便的訪問設(shè)備UI組件。比如,可以在頁面中使用Titanium提供的API控制導(dǎo)航條、工具欄、菜單,以及可以動態(tài)的向用戶彈出對話框、警告框等。除此,之外Titanium API還支持本地功能模塊的訪問,即用戶可以使用Titanium提供的APIs接口訪問數(shù)據(jù)庫、定位功能、文件系統(tǒng)功能、網(wǎng)絡(luò)功能、媒體功能等。

不過該框架圖,并沒有將Titanium中對多種腳本語言的相互訪問機制很好的表現(xiàn)出來。但是,這一機制卻又是Titanium框架的一個比較重要的功能特性。

三、Titanium構(gòu)建

Titanium的構(gòu)建過程使用scons管理(http://www.scons.org/)。scons是一個開源的軟件構(gòu)建工具,使用Python語言來描述軟件構(gòu)建規(guī)則。通過Titanium的源碼級構(gòu)建和Titanium的構(gòu)建規(guī)則兩個方面,可以了解Titanium運行環(huán)境由那些部分組成、這些模塊和模塊之間的關(guān)系是什么。

[注]以下所有的測試和分析內(nèi)容均是以Linux平臺上Desktop版本的Titanium代碼為基礎(chǔ)。

構(gòu)建Titanium所依賴的庫和環(huán)境

  • Ruby 1.8.x 開發(fā)包
  • Python 2.5.x開發(fā)包
  • scons構(gòu)建工具
  • git 版本管理工具

Ubuntu 9.04上構(gòu)建Titanium所需的支持包

  1. sudo apt-get install build-essential ruby rubygems libzip-ruby \ 
  2. scons libxml2-dev libgtk2.0-dev python-dev ruby-dev \ 
  3. libdbus-glib-1-dev libnotify-dev libgstreamer0.10-dev \ 
  4. libxss-dev libcurl4-openssl-dev 
  5. sudo apt-get install git-core 

獲取Titanium源碼

  1. git clone git://github.com/marshall/titanium 
  2. cd titanium 

獲取Kroll源碼

  1. git submodule init 
  2. git submodule update 
  3. cd kroll 
  4. git checkout master 

構(gòu)建Titanium測試程序

  1. cd .. 
  2. scons debug=1 

運行

  1. scons testapp debug=1 run=1 

有關(guān)Titanium構(gòu)建相關(guān)的信息,可以訪問以下頁面獲得:

http://wiki.github.com/marshall/titanium/build-instructions

3.2 Titanium構(gòu)建規(guī)則分析

3.2.1 版本需求

構(gòu)建過程所需的庫/程序版本
Python 2.5
Ruby 1.8
Scons 1.2
kroll 源碼版本 12/30/99
titanium_desktop 源碼版本 12/30/99
WebKit版本 libwebkittitanium-1.0.so.2.7.0
   

3.2.2 默認配置項

默認配置項
配置 備注
PRODUCT_VERSION 0.7.0  
INSTALL_PREFIX /usr/local  
PRODUCT_NAME Titanium  
CONFIG_FILENAME tiapp.xml  
BUILD_DIR build  
THIRD_PARTY_DIR kroll/thirdparty  
DISTRIBUTION_URL api.appcelerator.net  
CRASH_REPORT_URL api.appcelerator.net/p/v1/app-crash-report  
GLOBAL_NS_VARNAME Titanium 定義了全局Titanium對象名稱
     

3.2.3 scons編譯參數(shù)

Scons編譯參數(shù)
debug 0表示release版本,1表示debug版本
clean 清除構(gòu)建的工程
qclean 清除構(gòu)建的工程
run 運行TestApp
run_with 帶參數(shù)運行TestApp,好像Linux平臺上沒用

3.2.4 構(gòu)建規(guī)則文件

構(gòu)建規(guī)則文件
kroll/SConscript.thirdparty Titanium所需的第三方支持文件規(guī)則
installation/SConscript Titanium安裝器構(gòu)建規(guī)則
kroll/SConscript 構(gòu)建kroll庫規(guī)則
modules/SConscript 構(gòu)建語言支持模塊規(guī)則
apps/SConscript 構(gòu)建TestApp規(guī)則
SConscript.dist 構(gòu)建SDK規(guī)則
SConscript.docs 構(gòu)建APIs文檔規(guī)則
SConscript.test 構(gòu)建測試程序規(guī)則

3.2.5 核心庫和程序構(gòu)建規(guī)則

/程序 規(guī)則
build/linux/runtime/template/kboot kroll/boot/breakpad/common/*.c

kroll/boot/breakpad/common/*.cc

kroll/boot/breakpad/client/*.cc

kroll/boot/breakpad/processor/*.cc

kroll/boot/breakpad/client/linux/handler/*.cc

kroll/boot/breakpad/common/linux/*.cc

build/linux/runtime/libkroll.so kroll/api/*.cpp

kroll/api/config/*.cpp

kroll/api/binding/*.cpp

kroll/api/utils/*.cpp

kroll/api/utils/poco/*.cpp

kroll/api/utils/linux/*.cpp

kroll/api/net/proxy_config.cpp

kroll/api/net/*_linux.cpp

build/linux/runtime/libkhost.so kroll/host/linux/host.cpp

kroll/host/linux/linux_job.cpp

/linux/modules/api/libapimodule.so poco third library(http://pocoproject.org/)

kroll/modules/api/*.cpp

build/linux/modules/javascript/libjavascriptmodule.so poco third library(http://pocoproject.org/)

webkittitanium-1.0 third library

kroll/modules/javascript/*.cpp

build/linux/modules/ruby/librubymodule.so poco third library(http://pocoproject.org/)

libruby third library

kroll/modules/ruby/*.cpp

build/linux/modules/php/libphpmodule.so poco third library(http://pocoproject.org/)

kroll/modules/php/*.cpp

   

四、Titanium靜態(tài)分析

該部分主要是說明整個Titanium的閱讀工作量、弄清楚Titanium中定義的核心對象的功能作用,以及各個模塊之間的關(guān)系是什么。

4.1 代碼統(tǒng)計

這里,將Titanium項目代碼分成kroll和功能模塊擴展兩部分代碼來統(tǒng)計,數(shù)據(jù)如下兩表所示:

Kroll模塊代碼量統(tǒng)計
Language Files Blank Comment Code Scale Equiv
C/C++ Header 1168 35490
63506
111461
1.00
111461
HTML 386 1252 16112 51375 1.9 97612.5
C++ 162 6401 7046 33133 1.51 50030.83
Javascript 47 3273 1598 13214 1.48 19556.72
CSS 3 554 41 2720 1 2720
Object C 6 359 312 1400 2.96 4144
Python 10 260 185 1206 4.2 5065.2
Shell 11 56 157 234 3.81 891.54
Make 3 30 29 93 2.5 232.5
Assembly 1 15 39 57 0.25 14.25
Ruby 1 10 0 54 4.2 226.8
Yaml 1 0 0 12 0.9 10.8
SUM 1802 47938 89263 217012 1.35 293546.95
titanium_desktop模塊(排除Kroll模塊)
Language Files Blank Comment Code Scale Equiv
Javascript 118 5801 3276 28678 1.48 42443.44
C++ 125 4690 5169 27320 1.51 41253.2
C/C++ Header 159 1647 3443 7682 1 7682
HTML 49 347 39 3715 1.8 7058.5
Ruby 29 673 643 3227 4.2 13553.4
CSS 5 542 41 2655 1 2655
Python 45 601 664 2632 4.2 11054.4
C 1 167 237 1925 0.77 1482.25
Shell 13 60 158 251 3.81 956.31
PHP 5 37 1 179 3.5 626.5
XML 5 0 8 151 1.9 286.9
Object C 2 31 15 119 2.96 352.24
SUM 556 14596 13694 78534 1.65 129404.14

4.2 核心對象的介紹

對象 基類 說明
AccessorBoundObject StaticBoundObject settergetter的封裝,當(dāng)用戶訪問想訪問XXX屬性時,該對象會調(diào)用setXXX方法或者getXXX方法。目前Titanium中主要是JSTitanium對象使用AccessortBoundObject封裝
AccessorBoundMethod StaticBoundMethod 用于通過屬性的方式訪問方法,由該對象封裝的方法,會自動的導(dǎo)出settergetter方法
AccessorBoundList StaticBoundList 用于以屬性的方式訪問list對象,由該對象封裝的list,會自動導(dǎo)出settergetter
ArgList   對參數(shù)列表對象的封裝
Blob   對數(shù)據(jù)封裝,可以描述任何數(shù)據(jù)
Tuplex   對元組對象的封裝
DelegateStaticBoundObject KObject 用于對全局訪問對象的封裝,目前Titanium中只有UITitanium JS對象使用該對象封裝
KList KObject 封裝List對象
KMethod KObject 對方法的封裝,所有擴展語言的函數(shù),都需要用該對象封裝
KEventObject AccessorBoundObject 描述事件對象,JS中可以通過該對象,向主線程發(fā)送事件。比如重新載入頁面、彈出對話框。
KEventMethod KEventObject 對事件方法的封裝,目前只有ti.Process模塊使用該對象
KObject ReferenceCounted 所有的其他類型語言對象和方法都是繼承該類,這樣可以按照相同的方法處理不同語言對象和方法
StaticBoundList KList 靜態(tài)列表,使用內(nèi)部map綁定屬性
StaticBoundMethod KMethod 靜態(tài)方法
StaticBoundObject KObject 靜態(tài)對象,繼承該對象可以很方便的設(shè)置對象的屬性、方法。

每個StaticBoundObject內(nèi)部,都保存著一個StringShareValuemap成員屬性。

Value ReferenceCounted 描述對象類型
     

4.3 模塊之間的關(guān)系

從整體框架結(jié)構(gòu)上來看,可以將Titanium分成三個部分,最上層是WebKit以及針對WebKit的擴展(修改很少),中間層是kroll可以將其看成是一個中間件,最下層是個個模塊的擴展。模塊之間的關(guān)系如圖所示:

點擊查看大圖

以下從WebKit、Kroll和模塊擴展三個部分來說明

1、WebKit: 當(dāng)WebKit引擎解析頁面數(shù)據(jù)發(fā)現(xiàn)

首先,WebCore引擎會解析HTML頁面數(shù)據(jù),當(dāng)發(fā)現(xiàn)有標(biāo)簽,或者當(dāng)用戶觸發(fā)了頁面中某個與腳本函數(shù)相關(guān)的控件時,WebCore會將相應(yīng)的腳本代碼片段傳遞給JavascriptCore解析執(zhí)行。如果對比Tinanium修改的WebKit代碼和原始的WebKit代碼(http://www.webkit.org)會發(fā)現(xiàn),tinanium對WebKit的修改是及小的。主要是作了兩個方面的工作:首先,tinanium擴展了KURL的處理,增加了ti://, app://等私有協(xié)議的支持。再者,在WebKit/gtk/webkit/目錄中,添加了幾個接口函數(shù)(主要是用來處理擴展的協(xié)議和注冊解析器),其中最重要的是webkit_titanium_add_script_evaluator,該接口在Kroll模塊的script類中會被調(diào)用,用來向WebKit引擎注冊一個Evaluator Proxy。

2、Kroll和Base Module:這部分主要的職責(zé)是負責(zé)Javascript的方法、對象和Python、Ruby、PHP等語言之間相互轉(zhuǎn)換、事件處理,以及模塊動態(tài)加載。Kroll模塊中,定義了一個host對象,這個對象是整個TestApp的主線程,UI初始化、WebKit初始化和事件處理都是在host中完成的。host對象中保存了一個全局對象表,該表會在WebKit引擎、Python引擎、Ruby引擎之間以KObject中間對象形式相互傳遞,最終達到不同語言之間的相互調(diào)用。

3、API Extension:這里擴展了大量的與系統(tǒng)平臺功能相關(guān)的API共Web應(yīng)用使用。其中最重要的一個對象是ti.UI,該模塊負責(zé)UI相關(guān)的資源、事件處理、GTK主界面的創(chuàng)建、Tininum JS對象的創(chuàng)建。

五、Titanium動態(tài)分析

下面從6個方面以TestApp為例,來分析Titanium的主要特性和功能。

5.1 TestApp初始化

TestApp的啟動過程有個自啟動過程。首先,TestApp啟動后會創(chuàng)建一個Application對象,該對象會從Mainifest文件中獲取App相關(guān)的資源,并且保存在一個全局變量中。然后,TestApp會設(shè)置幾個系統(tǒng)環(huán)境變量:

  • KR_BOOTSTRAPPED: 描述是否已經(jīng)初始化環(huán)境變量以及構(gòu)建Application對象
  • KR_HOME:描述運行程序的HOME路徑
  • KR_RUNTIME:描述運行時資源路徑
  • KR_MODULES:描述需加載模塊信息
  • LD_LIBRARY_PATH:描述模塊所在的文件夾路徑

***,TestApp會使用exec系統(tǒng)調(diào)用將自己自啟,然后通過之前設(shè)置 KR_BOOTSTRAPPED環(huán)境變量判斷是否進入下一階段的初始化過程。如果 KR_BOOTSTRAPPED設(shè)置為YES,則會首先將其unset,然后啟動LinuxHost。

在titanium框架中,使用動態(tài)庫的方式將模塊之間的關(guān)系解耦合。在TestApp啟動的第二階段中,StartHost(kroll/boot/boot_linux.cpp)會根據(jù)之前設(shè)置的 KR_RUNTIME路徑信息,找到libkhost.so動態(tài)庫,然后從libkhost.so中獲取Execute函數(shù)指針,并且調(diào)用(這里有個問題,如果多個實列同時運行,有可能KR_RUNTIME尚未unset就啟動第二個應(yīng)用,則會出現(xiàn)TestApp異常)。

libkhost.so動態(tài)庫中的Execute方法,首先創(chuàng)建一個Host實例,在這里是LinuxHost對象,然后調(diào)用該對象的Run方法進入一個循環(huán)。這個循環(huán)是整個TestApp的主循環(huán),主要負責(zé)模塊的動態(tài)發(fā)現(xiàn)和加載,事件處理。在LinuxHost的實現(xiàn)中,會維護一個job隊列,通過定時器的方式,每隔250ms的時間會去檢測該job隊列中是否有job存在(LinuxJob描述)。如果,事件存在則會一次性將所有的事件取出,并且清空事件隊列,然后一個個的執(zhí)行job對象的Execute方法。

TestApp的兩次初始化過程如下圖所示:

 

 

點擊查看大圖

5.2 模塊初始化

TestApp程序創(chuàng)建LinuxHost對象,并且執(zhí)行Run方法之后,會首先掃描KR_MODULES環(huán)境變量中指定的模塊,并且從 LD_LIBRARY_PATH定義的路徑信息中尋找到這些動態(tài)庫模塊,并且加載(調(diào)用相應(yīng)模塊的Initialize方法)。LinuxHost首先加載的是基本模塊(API,PythonModule、RubyModule、PHPModule和JavascriptModule)。

以pythonModule為例,描述一個完整的加載過程:

  • Host::LoadModules從環(huán)境變量中獲取到python動態(tài)庫的路徑信息
  • 調(diào)用Host::FindBasicModules方法,將libpythonmodule.so文件加載進來,然后調(diào)用PythonModule的Initialize方法
  • PythonModule::Initialize首先會向全局屬性表中創(chuàng)建一個Python和PythonEaluator對象的關(guān)聯(lián)。前面也說到,Host對象會保存一個全局屬性表,這個表中使用KObject中間對象形式,將JAVASCRIPT、PYTHON、RUBY、PHP等語言定義的對象封裝,并且保存在該表中。運行時,可以使用Host對象的GetGlobalObject方法獲取。
  • 調(diào)用Script::AddScriptEvaluator靜態(tài)方法將PythonEvaluator對象放入Script對象中維護的一個Ealuator列表中。當(dāng)JavascriptCore引擎發(fā)現(xiàn)<script>標(biāo)簽會遍歷這個evaluator鏈表,通過MIME類型找到相應(yīng)的解析器實例,然后將代碼片段傳遞給相應(yīng)的解析器處理(這樣就可以支持HTML代碼中內(nèi)嵌多種語言)。

這里還有一個模塊比較特殊需要仔細說明,即ti.UI模塊。該模塊負責(zé)WebKit引擎初始化,GTK窗口創(chuàng)建以及UI事件的處理。加載過程類似PythonModule,首先Host對象找到libtiuimodule.so動態(tài)庫,然后調(diào)用Initialize方法初始化,ti.UI模塊中的Initialize方法只做了兩件事情,創(chuàng)建了一個APIBinding對象,然后將“API”屬性和APIBinding關(guān)聯(lián)起來,保存在全局屬性表中。接下來,當(dāng)Host::LoadModules方法加載完畢所有的動態(tài)庫后,會調(diào)用Host::StartModules來啟動模塊(在整個TestApp運行中,只有ti.UI模塊的Start方法被重載了,而其他模塊在StartModules方法被執(zhí)行時,什么事情都沒有做)。UIModule::Start方法做了三個非常重要的操作:1、創(chuàng)建GtkUIBinding對象,并且將“UI”和該對象綁定,存放在全局屬性表中。2、調(diào)用ScriptEvaluator::Initialzie()使用WebKit擴展中導(dǎo)出的webkit_titanium_add_script_evaluator函數(shù),將自己注冊到JavascriptCore中。3、創(chuàng)建初始化WebView。

至此,WebKit引擎已經(jīng)初始化完畢、UI界面已經(jīng)初始化完畢、相應(yīng)語言的解析器以及JAVACRIPT API擴展對象已經(jīng)添加到全局屬性表中。但是至此,頁面中是無法正常訪問Titanium對象的。

整個過程如下圖所示:

 

 

點擊查看大圖

5.3 Titanium對象的注冊

Javascript中的Titanium并沒有通過硬編碼的方式定義該名稱,而是在構(gòu)建的過程中通過變量的方式指定的。在構(gòu)建規(guī)則中有GLOBAL_NS_VARNAME變量,該變量名稱會作為編譯參數(shù)傳遞,代碼通過改變量的定義,來確定Javascript可見的Titanium主對象的名稱是什么。

當(dāng)webView構(gòu)建完畢后,Titanium Js主對象并不存在,只有當(dāng)***次WebKit遇到腳本代碼時,這個對象才被創(chuàng)建。當(dāng)WebKit引擎碰到腳本對象時,會調(diào)用JavascriptCore的initScipt方法,初始化Javascript引擎。在此JavascriptCore會將我們之前調(diào)用webkit_titanium_add_script_evaluator增加的Evaluator代理和JavascriptCore解析關(guān)聯(lián)起來。當(dāng)引擎和資源都初始化完畢,會向FrameClient發(fā)送object avaliable通知,會調(diào)用FrameLoader::dispatchWindowObjectAvaliable()方法。這個方法會導(dǎo)致UserWindow::RegisterJSContext()方法的調(diào)用。然后UserWindow對象會創(chuàng)建一個DelegateStaticBoundObject對象來描述Titanium對象,并且將之前初始化完畢的Titanium API對象(KObject)與Titanium對象關(guān)聯(lián)起來,然后將其放入到全局屬性表中。這樣,之后Web應(yīng)用程序就可以從全局屬性表中訪問到Titanium對象了。但是Titanium對象中有哪些子屬性是不知道的,這是運行時才去確定。

這個初始化過程如下圖所示:

 

 

點擊查看大圖

5.4 事件系統(tǒng)

Titanium的事件系統(tǒng)分成兩個部分來說明,一部分是如何獲取事件,另一部分是如何向事件系統(tǒng)中增加新事件。

當(dāng)linuxHost::RunLoop循環(huán)被調(diào)用后,立即會注冊一個定時器,每隔250ms調(diào)用一次main_thread_job_handler函數(shù)。該函數(shù)首先通過GetJobs方法獲取當(dāng)前系統(tǒng)中未處理的事件,并且依次的調(diào)用事件對象(LinuxJob)的Execute方法執(zhí)行。如果系統(tǒng)沒有未決的事件存在,則立即返回。

事件的添加和觸發(fā)均通過LinuxHost::InvokeMethodOnMainThread()方法完成。該函數(shù)會創(chuàng)建一個LinuxJob對象,并且插入到事件隊列尾中。事件的觸發(fā)有多種可能性,可以是由Javascript代碼觸發(fā),也可以是內(nèi)部事件觸發(fā),同樣也有可能是UI事件觸發(fā)。

由于Titanium擴展的JS API在C層上都會與相應(yīng)的C方法對應(yīng),當(dāng)Web應(yīng)用程序調(diào)用相應(yīng)的JS方法,對應(yīng)的C方法會被調(diào)用,該方法則會使用LinuxHost::InvokeMethodOnMainThread()方法,向主線程發(fā)送事件處理請求。

對于UI來說,在Linux平臺上所有的UI相關(guān)的事件首先是被GTK的應(yīng)用框架截獲,當(dāng)有UI事件到來時,ti.UI模塊會創(chuàng)建對應(yīng)事件的KEvent對象(在event.h中定義),然后調(diào)用KEvent對象的Fire方法,觸發(fā)事件。該方法會間接的使用LinuxHost::InvokeMethodOnMainThread方法向LinuxHost事件隊列注冊事件。

這個過程如下圖所示:

 

 

點擊查看大圖

5.5 訪問Titanium對象屬性和方法

比如,有一段Javascript腳本中調(diào)用Titanium.API獲取Titanium對象的API屬性,當(dāng)JavascriptCore解析到這部分代碼時,并不知道這個對象是什么類型的,完全當(dāng)作一個抽象的JSValue對象來對待,因為對于Javascript引擎來說,并不需要時刻知道對象是什么,有那些屬性和方法,只有到運行時才會去用查詢該對象中是否存在指定的屬性或者方法(JavascriptCore內(nèi)部維護了一張屬性表,通過查詢方式獲取相應(yīng)屬性或者函數(shù)的處理函數(shù)指針。這點V8做的就比較高明,用類的方式描述,動態(tài)將對應(yīng)JS的方法和屬性轉(zhuǎn)換成C++的成員函數(shù)和成員變量,大量的減少了訪問時間)。由于API這個對象是由Kroll創(chuàng)建的,是一個KObject對象,在掛載到Javascript 全局屬性表之前,Titanium會調(diào)用KObjectToJSValue方法,將KObject對象轉(zhuǎn)換成一個JS的Object對象,并且設(shè)置了幾個比較重要的回調(diào)函數(shù):

  • HasPropertyCallback: 當(dāng)查詢屬性時候被調(diào)用
  • GetPropertyCallback: 當(dāng)獲取指定屬性時被調(diào)用
  • SetPropertyCallback: 當(dāng)設(shè)置指定屬性時被調(diào)用

當(dāng)javascript訪問用Titanium對象的API屬性時,通過JSValue.Get方法會調(diào)用到GetPropertyCallback函數(shù),該函數(shù)會查詢KObject對象中(這里是說的Titanium)是否有API這個屬性,如果有則轉(zhuǎn)換成JSValue對象,并且返回給Javascript引擎。

如果這里訪問的是一個屬性的方法,過程和訪問對象是一樣的,只不過***創(chuàng)建的是一個Function Js對象,而非Object對象。當(dāng)Javascript訪問這個返回的Function對象時,Javascript引擎會調(diào)用callAsFunction方法,而該方法會引發(fā)CallAsFunctionCallback回調(diào)函數(shù)被調(diào)用(該函數(shù)是靜態(tài)函數(shù)在KMethodToJSValue函數(shù)中注冊)。這樣通過CallAsFunctionCallback這個回調(diào)接口,調(diào)用實際的KObject的Call方法,執(zhí)行實際的處理函數(shù)。

屬性訪問過程如下圖所示:

 

 

點擊查看大圖

5.6 Javascript、Python、Ruby動態(tài)語言間的相互調(diào)用

Titanium框架中引入了一個比較有意思的特性,即支持多種語言之間的相互調(diào)用。從實現(xiàn)技術(shù)角度來說,Titanium的多語言支持的設(shè)計思想,是在學(xué)習(xí)了WebKit的Binding機制而發(fā)展過來的。主要用到了JavascriptCore引擎可以動態(tài)注冊Evaluator的機制。HTML語言中定義了<script>標(biāo)簽,用于內(nèi)嵌腳本語言,該標(biāo)簽有個子屬性type,通過該屬性可以讓瀏覽器引擎區(qū)分是什么類型的腳本。加入我們有如下的腳本代碼:

  1. <script type=”text/python” src=”xxx.py”></script> 

首先,WebCore引擎會解析HTML頁面數(shù)據(jù),當(dāng)發(fā)現(xiàn)有<script>標(biāo)簽出現(xiàn),則會創(chuàng)建HTMLScriptElement,對于script有兩種處理情況,一種是如上代碼通過src包含一個腳本路徑,還有一種情況是定義一段代碼,通過控件或者超連接的方式以事件方式觸發(fā)。如果是***種情況,則會在創(chuàng)建HTMLScriptElement的時引發(fā)ScriptElementData::requestScript方法的調(diào)用。如果是第二種情況,則會在觸發(fā)相應(yīng)事件時候調(diào)用FrameLoader::executeScript方法執(zhí)行腳本。最終都會調(diào)用JavascriptCore中的EvaluatorAdapter::evaluate()。由于在初始化ti.UI模塊時,我們已經(jīng)注冊了自己的evaluator(ScriptEvaluator),因此會將獲取的腳本信息傳遞給ScriptEvaluator,在該對象中,會通過Script::Evaluate()方法,根據(jù)傳遞下來腳本的MIME類型(也就是script中text字段定義的類型)派發(fā)給注冊的不同解析器去執(zhí)行。

這里以Javascript調(diào)用Python代碼,并且Python代碼中又調(diào)用了ruby代碼為例子說明其調(diào)用過程。

Python代碼:

  1. def abc(): 
  2. ruby_fun() 

Ruby代碼:

  1. def ruby_func() 
  2. … 
  3. end 

當(dāng)pythonEvaluator::Evaluate()被調(diào)用后,首先將保存的全局JS對象表轉(zhuǎn)換成Python可識別的對象字典(KMethodToPyObject完成,轉(zhuǎn)換成PyKMethodType的Python對象)。這樣在之后編譯的Python代碼中就可以訪問到這些對象。然后將Python代碼使用Python編譯器編譯,并且將編譯后的函數(shù)對象轉(zhuǎn)換成KObject對象,插入到全局的JS對象表中(abc)。這樣,Javscript,和其他語言都可以識別該對象。同樣,對Ruby函數(shù)的處理,也會首先將全局JS對象表中的KObject對象轉(zhuǎn)換成Ruby的對象,然后對Ruby函數(shù)進行編譯,將新生成的Ruby函數(shù)對象(ruby_fun)轉(zhuǎn)換成KObject對象,然后從新更新JS全局對象轉(zhuǎn)換表。至此,全局JS對象表中就新增了兩個KObject對象:ruby_fun, abc。

當(dāng)javascript訪問該abc函數(shù)對象時,按照通常方式首先調(diào)用CaAsFunctionCallback,該函數(shù)會調(diào)用KObject的Call方法,由于該KObject實際上就是一個KPythonMethod對象,因此KPythonMethod對象的Call方法會被調(diào)用。之前我們注冊的Python方法是一個PyKMethodType,該類型中定義了一個方法回調(diào)函數(shù),當(dāng)Python方法被調(diào)用時,該回調(diào)函數(shù)(PyKMethod_call)會被調(diào)用。這個例子中,在Python代碼里調(diào)用了ruby_fun,因此當(dāng)PyKMethod_call被調(diào)用時,首先將調(diào)用的KObject對象(實際上是一個對Ruby函數(shù)對象的封裝)轉(zhuǎn)換成KMethod對象,然后調(diào)用Call方法。這樣就通過間接調(diào)用,調(diào)用到KRubyMethod的Call方法,使得Ruby函數(shù)得到執(zhí)行。

整個過程如下圖所示:

 

 

點擊查看大圖

六、參考資源

http://www.appcelerator.com/

責(zé)任編輯:佚名 來源: 姜江的博客
相關(guān)推薦

2012-04-19 17:16:32

Titanium實例代碼分析

2012-05-18 11:29:55

Titaniumpros

2012-05-18 11:34:03

Titaniumcons

2012-04-20 11:07:12

Titanium

2012-06-26 10:40:43

Titanium

2012-04-19 12:58:26

TitaniumJSS

2012-04-19 13:55:19

TitaniumTiMVC

2012-05-17 09:09:05

Titanium單元測試

2012-06-14 09:42:20

跨平臺工具AppceleratoTitanium

2012-04-19 13:52:16

TitaniumMVCRedux

2012-04-19 16:22:12

TitaniumTabGroup

2012-05-23 09:41:37

Titanium St卸載

2012-05-18 10:08:56

TitaniumAndroid

2012-05-18 11:28:57

TitaniumCommunity W

2012-05-23 09:28:14

Titanium錯誤應(yīng)對辦法

2012-04-19 11:40:21

Titanium

2012-04-19 16:41:24

Titanium視頻實現(xiàn)頁面跳轉(zhuǎn)

2012-05-23 09:33:37

TitaniumStudioAndroid APK

2012-05-23 09:46:15

Titanium MoTitanium

2012-05-18 11:16:42

@Kroll注解詳解TitaniumAndroid模塊
點贊
收藏

51CTO技術(shù)棧公眾號