王 超 沈立煒 趙文耘
1(復旦大學軟件學院 上海 201203) 2(復旦大學計算機科學技術學院 上海 201203) 3(上海市數據科學重點實驗室 上海 201203)
屏幕觸摸是移動設備上最主要的人機交互渠道,它能提供例如下拉刷新、左右滑動等應用特性,這些特性豐富了界面的展示效果。為了實現這些特性,安卓應用開發者需要基于最基本的onTouchEvent等事件機制集成應用響應邏輯,但依舊需要編寫相應代碼以識別觸控的事件類型,如手指的下拉、釋放等。
谷歌從2011年開始提供安卓支持庫來輔助開發者,這些支持庫對開發者經常需要的功能進行了封裝,其中包括了對特定類型界面觸控事件的封裝,例如SwipRefreshLayout控件集成了下拉刷新的功能、DrawerLayout控件集成了左右滑動的功能。使用這些支持庫不僅提高了開發者的開發效率,而且能夠在低版本的安卓平臺上使用高版本的功能。但許多開發者對安卓支持庫提供的功能缺乏了解,因此將已有代碼替換成支持庫需要花費很多的精力去學習,比如開發者需要對安卓支持庫中下拉刷新、左右側滑等控件的代碼結構和實現機制有深入的了解。此外,對于維護采用基本事件處理機制編寫的安卓應用程序,沒有相應的技術來提醒安卓應用維護者進行支持庫的替換,因此維護人員需要花費額外的精力在應用程序的源碼中尋找可替換的功能代碼。
目前已經有的代碼替換工作主要集中在API和Library庫的遷移。例如將項目中涉及的棄用API(Deprecated API) 用新的API進行遷移[1]。再比如隨著軟件系統生命周期的變化,對于系統中已有的依賴庫需要用更相關的庫來進行遷移[2]。而對于將已有功能代碼替換成安卓支持庫中相應控件實現的代碼,目前還沒有很好的方法來支持。
針對上述目標,本文提出了一種面向安卓觸控類支持庫的應用代碼替換技術,其利用android.support.v4.widget支持庫下的觸摸控件并以自動化的方式尋找目標應用中的可替換點,最終為應用開發者和維護者生成替換建議。具體而言,本文首先提出用以描述安卓事件回調方法代碼特征的元模型,以此為基礎將目標代碼特征模型與安卓支持庫各控件的特征模型進行匹配。當匹配的結果能夠進行替換時,分別從功能的實現代碼、監聽器的綁定、layout資源文件這三個方面生成替換建議。實驗結果表明本文所提技術能夠為支持庫控件相應的,且用基本觸控邏輯來實現的事件回調方法及其資源布局給出正確的替換建議。安卓開發者利用本文方法,可以分析出應用程序中的哪些代碼可以進行替換,以及用安卓支持庫中的哪一個觸摸控件進行替換。
與本文相關的研究工作主要包括安卓應用分析、代碼相似度檢測、代碼遷移技術這三個方面。
安卓應用分析方法主要分為動態分析和靜態分析兩大類。動態分析是指當應用程序在運行時對應用程序的各種行為進行分析,以獲取程序的動態行為特征。靜態分析則是分析應用程序的源碼或者字節碼,構造應用程序的整體結構。對于安卓靜態分析,目前一些研究工具利用不同類型的圖來描繪程序的特征,如控制流圖、數據流圖等[3-4]。為了獲取安卓應用程序的源碼或字節碼,需要對APK安裝包反編譯,常用的反編譯工具有Dexpler[5]、Smail[6]和AndroGuard[7]。本文方法也依賴于安卓靜態分析技術,在安卓應用程序的源碼層面上利用抽象語法樹分析結果來進一步描繪程序的特征。
針對代碼的相似問題目前已有很多分析方法,如基于文本識別、基于度量值、基于代碼結構和基于圖結構的代碼相似分析。基于文本識別的代碼相似分析方法是將代碼表示成文本或token序列的方式,進而采用模式匹配技術來檢測代碼間是否相似。代碼克隆[8]就是基于文本識別的方法來檢測待分析代碼中的重復部分。基于度量值的代碼相似分析方法,不直接比較程序代碼,而是提取選定的度量值信息,形成一組包含這些信息的特征向量,通過比較這些特征向量來比較代碼的相似程度[9]。衡量代碼的度量值有很多,如圈復雜度、類耦合度和繼承深度等。基于代碼結構的代碼相似分析方法是將待分析的代碼轉化成抽象語法樹,進而在語法樹上使用匹配或搜索技術尋找相似的子樹[10-11]。基于圖結構的代碼相似分析是將程序代碼表示成程序依賴圖來進行分析[12-13]。從兩個特定的起始點開始,尋找兩幅圖中的最大相似子圖。本文方法也利用了基于代碼結構相似的分析方法,將安卓應用程序代碼構造成抽象語法樹,進而在抽象語法樹的基礎上利用樹匹配算法進行相似分析。
代碼遷移目前主要分為API遷移和Library庫的遷移。對于API的遷移,可以通過比較兩個版本API在庫中的聲明變化以及兩個版本API在代碼中的使用方式來進行遷移[14]。對于Library庫的遷移,通過對大量開源軟件項目的分析來識別相似庫之間的遷移變化,進而根據大量的分析數據來為Library庫的遷移提供建議[2]。與上述工作不同,本文方法關注控件支持庫層面的遷移,涉及一組代碼語句與控制結構,其中的核心要素是識別目標代碼與安卓支持庫中特定控件在功能和結構上的相似性。
圖1為開發者使用基礎回調方法onTouch實現的下拉刷新功能:當手指下拉并松開后,在屏幕上發送一條通知。該代碼在基礎回調方法的UP分支下實現發送通知的業務邏輯。

圖1 下拉刷新案例功能代碼
圖2為該應用程序相應的資源文件,其中子視圖由兩個文本框TextView構成,這兩個文本框在LinearLayout布局的內部。

圖2 下拉刷新案例資源文件
圖1的功能代碼和圖2的資源文件都可以用安卓支持庫中已經封裝好的控件進行替換。當安卓應用軟件開發者需要用安卓支持庫中已有的控件進行替換時,先要判斷是否能夠替換以及用什么控件進行替換,然后還要分別從功能代碼和資源文件兩塊進行替換。
對于開發者來說這將會面臨很多困難。首先許多安卓開發者對安卓支持庫下提供的功能并不了解,因此將已有代碼替換成支持庫需要一定的學習代價。雖然擁有了一定的安卓支持庫的儲備知識,但沒有相應的技術提醒開發者該應用程序中的某些功能能夠用安卓支持庫中的控件進行替換。此外,一些開發者知道該項目的有些功能可以使用支持庫的控件進行替換,但是他們不知道如何在項目中進行替換。
當開發者使用基于本文方法所開發的工具時,就可以根據工具生成的建議快速地在項目中進行支持庫的替換。該工具將會從功能實現代碼、監聽器的綁定和布局文件這三個方面給出替換建議。
圖3為根據替換建議用SwipeRefreshLayout這個支持庫控件進行替換后的功能代碼。該代碼中,遷移的代碼被放置在SwipeRefreshLayout的onRefresh回調方法中,同時為SwipeRefreshLayout綁定OnRefresh-Listener監聽器,用來監聽事件。

圖3 用支持庫控件替換后的功能代碼
資源文件的替換如圖4所示。根據替換建議,使用SwipeRefreshLayout控件節點來替換原先的LinearLayout節點。

圖4 用支持庫替換后的資源文件
圖5所示的元模型用來描繪安卓事件回調方法的代碼特征信息。該元模型既可以表示支持庫中的回調方法,又可以用來描述目標替換代碼的方法代碼結構。

圖5 安卓事件回調方法的代碼特征元模型
Widget表示安卓支持庫中的一個觸摸控件,在該元模型中,控件包含了一組監聽器。每一個監聽器負責監聽一個或多個事件并觸發相應的回調方法(Callback)。我們使用一棵特征樹(FeatureTree)來表示Callback的具體代碼及其應用邏輯,并以FeatureTreeRoot來表示該特征樹的根節點。根節點一般命名為基礎回調的方法名,例如onTouch、onTouchEvent等。
特征樹是由一系列表示代碼元素的節點構成,即CodeElement。節點之間存在Order信息與Include關系。Order關系表示同層次代碼元素與同層次代碼元素之間的次序關系,Include關系表示外部代碼元素與內部代碼元素之間的包含關系。另外,每一個節點包含KeyWordSet屬性,用以代表代碼元素中的關鍵字集合。該集合可包括方法名以及部分靜態常量名。這些關鍵字從SDK中提取得來,用以反映代碼的實現功能。
元模型中列舉了三種特定類型的代碼元素,即代碼控制結構(ControlStructure)、代碼語句(Statement)和插樁點(Instrumentation)。
ControlStructure用來描述代碼的骨架結構,表示程序執行的動作順序。本文將控制結構分成兩類,循環結構(Loop)和分支結構(Branch)。循環結構包括For、While、Do等,分支結構包括If、Switch等。
Statement用來記錄代碼結構中的基本語句信息,例如方法調用信息,Statement就記錄了該方法調用是在代碼控制結構中的哪個分支下進行調用的。
Instrumentation記錄控件回調方法在代碼中的哪個位置被間接觸發。例如SwipeRefreshLayout控件中的onRefresh回調方法是在onTouchEvent這個基礎回調方法中的UP分支下被間接觸發的。在進行代碼替換時,用戶實現業務功能的代碼就放在該插樁點所記錄的回調方法的內部。
算法1是目標代碼特征模型的構造方法。該算法的輸入是一個Callback方法,對Callback方法中的每一個結構塊進行迭代分析。算法的輸出是FeatureTree,即一個以樹狀結構表示回調方法的特征模型。
算法1目標代碼特征模型的構造方法
Function: BuildFeatureTree
輸入: Callback。
輸出: FeatureTree。
begin
For each ControlBlock in Callback
begin
CNode=CreateNode(Loop/Branch)
CreateOrder(PreCNode, CNode)
SNode=CreateNode(Condition)
AddIncludeNode(CNode, SNode)
BNode=CreateNode(Statement)
AddIncludeNode(SNode, BNode)
PreCNode=CNode
end
return FeatureTree
end
在迭代過程中,對于每一個結構塊,創建一個ControlStructure類型的節點,節點記錄該控制結構的類型是Loop還是Branch,并將此控制結構節點與父控制結構節點關聯起來。為了記錄控制結構之間的Order關系,在關聯兩個控制結構節點時以Order屬性的邊來連接這兩個節點。控制結構中的條件信息,用Statement類型的節點來保存,并將該節點以Include關系關聯到所屬的控制結構節點上。對于某一個條件下的代碼語句,仍然用Statement類型節點來保存,并將該節點以Include關系關聯到所對應的分支條件節點上。如果該控制結構是分支結構,則需要對分支結構下的每一個分支條件進行分析。
首先需要為支持庫每一個觸摸控件中每一個監聽器下的每一個回調方法構造特征模型。為了獲取支持庫控件中的回調方法,可以通過參閱文檔或檢索支持庫中具有Listener的類來找到相應的回調方法。為了找到觸發回調方法的調用語句,需要對回調方法進行回溯,由于回調方法有時候并不能在某一個方法中找到對其的調用,因此回溯過程將分為以下兩種情形:
(1) 如果在某一個方法中找到觸發該回調方法的調用語句,則以該方法繼續向上回溯。
(2) 如果沒有找到觸發該回調方法的調用語句,則利用事先對安卓內部回調方法的總結,找到觸發該回調方法的方法,然后以該方法繼續向上回溯。
算法2描述了回調函數調用鏈的回溯過程,該算法的輸入是一個支持庫控件中的回調方法,輸出是控件中的基礎回調方法。通過算法2,可以將控件中以回調方法為終點,以基礎回調方法為起點的方法調用鏈構建完成。接著采用算法1,對基礎回調方法進行特征模型樹的構造。此時的特征模型樹需要加上插樁類型節點,該節點存儲了控件中的某個回調方法,并且將該節點連接到基礎回調方法對應的代碼塊下。
算法2回調函數調用鏈的回溯算法
Function: SearchBaseMethod
輸入: Callback。
輸出: BaseMethod。
begin
if Callback是基礎回調方法 then
begin
BaseMethod=Caller
return BaseMethod
end
if 找到該回調方法的Caller then
begin
SearchBaseMethod(Caller)
end
else then
begin
通過整理的回調方法總結中找到Caller
SearchBaseMethod(Caller)
end
end
圖6給出了一個控件特征模型的例子。onTouchEvent是SwipeRefreshLayout控件內部的一個基礎回調函數。

圖6 特征模型樹示例
可以看出,其內部是一個分支類型的控制結構,用ControlStructure類型的節點來表示,節點存儲了該控制結構類型為Branch類型。該結構有三個分支,分別用三個Statement類型的節點保存分支條件的信息。每一個分支條件下用Statement類型節點保存該分支下的代碼語句片段信息。由于UP分支下間接調用了onRefresh這個回調方法,因此用一個插樁類型的節點來存儲該回調方法信息。
代碼替換技術的方法流程如圖7所示,該方法流程主要分成兩個階段,第一階段是安卓支持庫特征模型的準備,第二階段是基于第一階段支持庫特征模型的代碼替換技術。

圖7 代碼替換技術的方法流程
安卓支持庫特征模型的準備分成兩個部分:一是回調方法調用鏈的構建,二是回調方法特征模型的構建。回調方法調用鏈的構建是對于安卓支持庫控件中的每一個回調方法,找到該方法是在哪個基礎回調方法中被觸發的。回調方法特征模型的構建是對控件中的每一個回調方法構建特征模型樹。
支持庫特征模型的代碼替換分成三個部分,分別是基于支持庫特征模型的待替換代碼的定位、匹配和替換。首先需要對待分析的安卓應用進行掃描,對應用中每一個Activity中的每一個回調方法進行定位。如果該回調方法名與支持庫特征模型中的某個基礎回調方法名一致,則該回調方法是一個潛在待替換代碼。如果方法名不一致,則繼續定位應用中的下一個回調方法。對于定位到的一個潛在待替換代碼,采用樹匹配的算法將潛在待替換代碼特征模型樹與控件中相對應的特征模型樹進行匹配,根據匹配結果判斷能否進行替換。當可以替換時,生成相應的替換建議。
為了對目標代碼特征模型樹和安卓支持庫控件的特征模型樹進行匹配比較,本文采用一種樹匹配算法(TM)來尋找兩棵特征模型樹間的最大匹配。S(SA,S1,S2,…,Si)和T(TB、T1,T2,…,Tj)分別是目標代碼特征模型樹和安卓支持庫控件特征模型樹。其中:Si為樹S的第一層子樹的第i個節點;Tj為樹T的第一層子樹的第j個節點;SA和SB分別為樹的根節點。M為兩個特征模型樹的匹配,最大匹配M就是擁有最多節點對間的匹配,其最大匹配節點個數為M+1,加1是因為根節點也是匹配的節點對。為了求出M(
1) 當兩個子樹中有一個為空是,匹配數M為0。
2) 當兩個子樹都不為空時,可分為以下幾個情形:
(1) 匹配Si和Tj,這時M(
(2) 匹配Si,這時M(
(3) 匹配Tj,這時M(
最后根據樹匹配算法的結果,計算出兩個特征模型之間的相似度:
式中:Node(S)和Node(T)分別表示樹S和樹T節點的個數;TM(S,T)表示通過樹匹配算法計算后返回的兩棵樹間的最大匹配的節點個數。
圖8所示為兩個特征模型樹S和T,節點中的標號表示該節點的類型,具有相同標號的節點看成是相同節點。利用TM算法可以求出S和T之間的最大匹配為9,因此它們之間的相似度為0.9。

圖8 兩棵特征模型樹
因此兩棵特征模型樹的最大匹配節點個數越多,則兩棵樹的相似度就越大,也就越相似。對于本文的場景,需要在目標代碼的特征模型樹中匹配到一棵子樹,該子樹即控件基礎回調方法的特征模型樹。所以最大匹配樹TM(S,T)滿足以下關系時,目標代碼可以用安卓支持庫里的控件進行替換:
TM(S,T)=Node(T)
式中:T表示的是安卓支持庫控件代碼的特征模型樹;S表示的是目標代碼的特征模型樹;Node(T)表示樹T節點的個數;TM(S,T)表示通過樹匹配算法計算后返回的兩棵樹間的最大匹配的節點個數。
1) 功能實現代碼和監聽器的替換。算法3描述了功能實現代碼和監聽器的替換方法。該算法的輸入是兩個特征模型樹,分別是目標代碼的特征模型樹CallbackFeatureTree和能夠用來替換該目標代碼的支持庫控件中的基礎回調方法的特征模型樹BaseMethodFeatureTree。該算法用CodeSegmentMap來保存能夠被遷移的代碼片段,用NotReplaceSet來保存未被遷移的代碼片段。
算法3功能實現代碼和監聽器的替換算法
Function: CallbackReplace
輸入: CallbackFeatureTree, BaseMethodFeatureTree。
輸出: CodeSegmentMap, NotReplaceCodeSet。
begin
for each Statement in CallbackFeatureTree
begin
if Statement 對應到BaseMethodFeatureTree中的一個插樁點 then
begin
for each widget in WidgetSet
begin
for each FeatureTreeRoot in widget
begin
if FeatureTreeRoot==BaseMethodFeatureTree.root then
begin
find Listener where Listener.contain(FeatureTreeRoot)
CodeSegmentMap.put(控件+監聽器+插樁點, Statement)
end
end
end
end
if Statement 對應不到BaseMethodFeatureTree中的一個節點 then
begin
NotRepalceCodeSet.put(Statement)
end
end
return CodeSegmentMap, NotReplaceCodeSet
end
在算法3中,以CallbackFeatureTree為基準,遍歷該特征模型樹上的Statement類型節點,如果該節點直接對應到BaseMethodFeatureTree中的一個非插樁節點,那么說明新控件已經包含這些語句。如果對應的是一個插樁類型的節點,說明該代碼語句是可以進行遷移的。如果沒有對應到任何一個節點,則將該代碼語句記錄到NotReplaceCodeSet中,該代碼語句無法被遷移。對于監聽器的搜索,首先找到BaseMethodFeatureTree是在哪個widget下的,然后在該Widget下找到哪一個listener的孩子節點中有一個孩子節點是該BaseMethod的,則該listener就是需要用來替換的監聽器。最后以插樁點、監聽器和該控件作為key鍵,Statement作為值,記錄到CodeSegmentMap中。
2) layout資源文件的替換。layout資源文件的替換分成兩步:第一步需要找到待替換的控件是什么;第二步需要找到資源文件是哪一個。在Callback所處的Activity中,可以找到該回調的監聽器,然后向上回溯找到是哪一個對象set了這個監聽器,則該對象就是需要找的待替換控件。一個Activity的資源文件是在該Activity中的onCreate方法內部的setContentView方法中被加載的,該方法中的參數就是layout資源文件的名字。例如方法參數是R.layout.activity_main,則需要的資源文件名稱就是activity_main.xml。
接著需要在該資源文件中搜索到用戶控件的節點,當找到該節點后,將該節點用支持庫控件進行替換。算法4描述了節點搜索的方法。
算法4搜索節點的算法
Function: depthSearch
輸入: root//xml文件的根節點。
輸出: child//待替換的控件節點。
begin
nodeStack.add(root)
while(!node.isEmpty)
begin
node=nodeStack.pop()
list=node.getChildren()
for child ∈ list
begin
nodeStack.add(child)
if child.name==layout.name then
begin
return child
end
end
end
end
算法4的實質是樹的深度優先搜索算法,由于Activity是由一組ViewGroup組成,所以從根節點出發,依次遍歷每一組ViewGroup。對于每一組ViewGroup,依次搜索其每一個孩子節點分支,然后再以該孩子節點為起點,照此方法直到搜索到某一分支的葉子節點時返回上一層繼續搜索。當搜索到節點的名字屬性與待替換控件的名字屬性一致時就停止搜索,那么該位置的節點就是需要用新的控件去替換的位置。
本文給用戶提供的生成建議包含以下幾個部分:
1) 對于安卓應用中可以進行遷移的代碼,需要將支持庫控件、監聽器、回調方法、可遷移代碼組合成完整的代碼片段。為了方便用戶的理解,該建議還增加了一些文字描述,將這些描述與組合后的代碼片段作為完整的可遷移代碼的替換建議。圖9給出了可遷移代碼建議的模板。

圖9 可遷移代碼的建議模板
在替換建議中,圖9模板先給出了替換前的代碼,并用文字指明了該代碼片段位于哪個Activity的哪個基礎回調方法,然后給出了遷移后的代碼示例,也用文字介紹了使用安卓支持庫中的哪個控件進行替換,以及綁定的監聽器和回調方法的信息。
2) 對于安卓應用中未被遷移的代碼,本文同樣將未被遷移代碼和一些文字描述作為替換建議展示給用戶。圖10給出了未被遷移代碼建議的模板,其既給出了未被遷移的代碼片段,又給出了該代碼片段是位于該應用中的哪個Activity里的哪個基礎回調方法下的。

圖10 未被遷移代碼的建議模板
3) 對于資源文件的替換,本文依舊給出原資源文件和替換后的資源文件,同時也通過文字描述進行解釋,方便用戶的定位和替換。圖11給出了資源文件替換建議的模板,文字描述告訴用戶資源文件的名稱,以及是用支持庫中的哪個控件進行替換。

圖11 資源文件替換的建議模板
圖12為基于本文方法所設計的工具界面,該工具的界面分成上下兩個部分。上半部分是用戶的輸入部分,用戶需要提供待分析的安卓項目的地址。下半部分是替換建議生成部分,分別從可遷移代碼、資源文件替換和未被遷移代碼三個方面給出替換建議。界面中的三個文本框分別用來展示這三個方面的替換信息。

圖12 工具界面
本文主要通過兩組實驗來對本文方法在實際開發中的實用性進行分析,這兩組實驗分別是針對用戶開發應用的支持庫替換實驗和針對開源應用的支持庫替換實驗。
1) 針對用戶開發應用的支持庫替換實驗。本實驗邀請了三位具有初級安卓開發經驗的同學,讓這三位同學基于基礎回調方法實現例如下拉操作、側滑操作等功能的安卓應用程序。表1列舉了給這三位同學安排的開發任務和提供的開發建議。

表1 實驗的開發任務與開發建議
當三位同學完成應用開發后,利用本文方法對這三個應用進行替換分析。最終的分析結果如表2所示。

表2 實驗結果
其中有兩個應用有替換建議,有一個應用沒有替換建議。本節將選取實驗1和實驗3,即一個有替換建議的例子和一個沒有替換建議的例子來對該實驗進行分析。
(1) 有替換建議的例子分析。該例子用onTouchEvent這個基礎回調方法實現下拉刷新的功能。圖13是該功能實現代碼的片段。該例子在onTouchEvent的Up分支下寫了一段更新子視圖的邏輯,該邏輯是當手指下拉松開后,在子視圖的ListView中添加一行List。

圖13 功能實現代碼片段
通過本文方法分析后,安卓支持庫里的下拉刷新控件SwipeRefreshLayout可以對例子中用基礎回調方法onTouchEvent實現的下拉刷新代碼進行替換。圖14是可遷移代碼的替換建議,可待遷移代碼放置在SwipeRefreshLayout的onRefresh回調方法中,該回調方法是在手指下拉手松后被間接觸發的。同時為Swipe-RefreshLayout綁定一個setOnRefreshListener監聽器,用來監聽事件。

圖14 可遷移代碼的替換建議
該例子的資源文件如圖15中替換前的代碼所示,該資源文件有兩個視圖,分別是子視圖ListView和父視圖LinearLayout,子視圖ListView在父視圖LinearLayout的內部。對于替換后的資源文件如圖15中替換后的代碼所示, ListView這個子視圖在SwipeRefreshLayout控件節點的內部。

圖15 資源文件的替換建議
(2) 無替換建議的例子分析。該例子沒有替換建議是因為該例子將下拉刷新的邏輯用一個類封裝好,所以在Activity中只保留了更新子視圖的邏輯,對于下拉刷新的邏輯則在那個類中進行實現。圖16展示了Activity中處理業務邏輯的代碼片段。PullRefreshLayout是封裝好的類,在Activity中直接創建該類的一個對象,然后綁定相應的監聽器來監聽動作,在該例子中使用的是setRefreshListener。

圖16 無替換建議的實現代碼
2) 針對開源應用的支持庫替換實驗。本部分實驗從開源社區上找了五個與安卓支持庫觸摸控件功能相似的開源安卓應用項目,然后利用本文的方法對這五個安卓應用項目進行替換分析。本實驗所選取的開源應用的來源信息如表3所示,最終分析結果如表4所示。

表3 開源項目來源

表4 開源項目實驗結果
可以看出,這五個案例中有2個案例有替換建議輸出,有3個案例沒有替換建議輸出。其中能夠進行替換的項目均包含與支持庫控件相應的,且用基本觸控邏輯來實現的事件回調方法。相對地,在三個沒有替換建議輸出的應用中,有一個是使用了封裝好的功能類來實現對應的功能,有兩個是直接使用了安卓支持庫中的控件。對于將功能封裝成一個類的情形,本文給出的方法同樣也可以進行分析替換,但這樣做的意義不大。由于用戶已經將一個功能封裝好了,那就沒有必要再去用安卓支持庫里的控件進行替換,因此本文設計的方法對封裝好的功能類是不進行分析的。
本文提出了一種面向安卓觸控類支持庫的應用代碼替換技術。首先設計了一種用于描述安卓事件回調方法中代碼特征的元模型,其不僅能夠表示支持庫中的回調函數,也可以用來描述目標替換代碼中的方法代碼結構;接著基于安卓支持庫的特征模型和目標替換代碼的特征模型進行匹配;最后對于可以進行替換的目標代碼,設計了一種涵蓋功能實現、頁面布局的代碼替換建議生成方法。
本文方法仍然有一些不足的地方,需要在后續工作中不斷完善。第一,目前只是針對安卓觸摸類控件進行替換分析,對于支持庫中的其他功能目前還無法做到替換分析;第二,本文方法的實現與用戶交互的功能還不夠完善,后續將對該方法實現進行擴展,增加與用戶交互的功能。