日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > 互聯(lián)網(wǎng) > Appium Android Bootstrap源碼分析之控件AndroidElement

Appium Android Bootstrap源碼分析之控件AndroidElement

來(lái)源:程序員人生   發(fā)布時(shí)間:2014-11-17 08:28:57 閱讀次數(shù):4061次

通過(guò)上1篇文章《Appium Android Bootstrap源碼分析之簡(jiǎn)介》我們對(duì)bootstrap的定義和其在appium和uiautomator處于1個(gè)甚么樣的位置有了1個(gè)初步的了解,那末依照正常的寫(xiě)書(shū)的思路,下1個(gè)章節(jié)應(yīng)當(dāng)就要去看bootstrap是如何建立socket來(lái)獲得數(shù)據(jù)然后怎樣進(jìn)行處理的了。但本人覺(jué)得這模樣做其實(shí)不會(huì)太好,由于到時(shí)整篇文章會(huì)變得非常的冗雜,由于你在編寫(xiě)的進(jìn)程中碰到不認(rèn)識(shí)的類(lèi)又要跳入進(jìn)去進(jìn)行說(shuō)明分析。這里我覺(jué)得應(yīng)當(dāng)嘗試吸取著名的《重構(gòu)》這本書(shū)的建議:1個(gè)方法的代碼不要寫(xiě)得太長(zhǎng),不然可讀性會(huì)很差,盡可能把其分解成不同的函數(shù)。那我們這里就是用類(lèi)似的思想,不要嘗試在1個(gè)文章中把所有的事情都做完,而是嘗試先把關(guān)鍵的類(lèi)給描寫(xiě)清楚,最后才去把這些類(lèi)通過(guò)1個(gè)實(shí)例分析給串起來(lái)顯現(xiàn)給讀者,這樣大家就不會(huì)由于1個(gè)文章太長(zhǎng)影響可讀性而放棄往下學(xué)習(xí)了。

那末我們這里為何先說(shuō)bootstrap對(duì)控件的處理,而非剛才提到的socket相干的sockethttp://www.jyygyx.com/server/的建立呢?我是這模樣看待的,大家看到本人這篇文章的時(shí)候,很有可能之前已了解過(guò)本人針對(duì)uiautomator源碼分析那個(gè)系列的文章了,或已有uiautomator的相干知識(shí),所以腦袋里會(huì)比較迫切的想知道究竟appium是怎樣應(yīng)用了uiautomator的,那末在appium中于這個(gè)問(wèn)題最貼切的就是appium在http://www.jyygyx.com/server/端是怎樣使用了uiautomator的控件的。

這里我們主要會(huì)分析兩個(gè)類(lèi):

  • AndroidElement:代表了bootstrap持有的1個(gè)ui界面的控件的類(lèi),它具有1個(gè)UiObject成員對(duì)象和1個(gè)代表其在下面的哈希表的鍵值的String類(lèi)型成員變量id
  • AndroidElementsHash:持有了1個(gè)包括所有bootstrap(也就是appium)曾見(jiàn)到過(guò)的(也就是腳本代碼中findElement方法找到過(guò)的)控件的哈希表,它的key就是AndroidElement中的id,每當(dāng)appium通過(guò)findElement找到1個(gè)新控件這個(gè)id就會(huì)+1,Appium的pc端和bootstrap端都會(huì)持有這個(gè)控件的id鍵值,當(dāng)需要調(diào)用1個(gè)控件的方法時(shí)就需要把代表這個(gè)控件的id鍵值傳過(guò)來(lái)讓bootstrap可以從這個(gè)哈希表找到對(duì)應(yīng)的控件

1. AndroidElement和UiObject的組合關(guān)系

從上面的描寫(xiě)我們可以知道,AndroidElement這個(gè)類(lèi)里面具有1個(gè)UiObject這個(gè)變量:
public class AndroidElement { private final UiObject el; private String id; ... }
大家都知道UiObject其實(shí)就是UiAutomator里面代表1個(gè)控件的類(lèi),通過(guò)它就可以夠?qū)丶M(jìn)行操作(固然終究還是通過(guò)UiAutomation框架). AnroidElement就是通過(guò)它來(lái)跟UiAutomator產(chǎn)生關(guān)系的。我們可以看到下面的AndroidElement的點(diǎn)擊click方法其實(shí)就是很干脆的調(diào)用了UiObject的click方法:
public boolean click() throws UiObjectNotFoundException { return el.click(); }
固然這里除click還有很多控件相干的操作,比如dragTo,getText,longClick等,但無(wú)1例外,都是通過(guò)UiObject來(lái)實(shí)現(xiàn)的,這里就不逐一羅列了。

2. 腳本的WebElement和Bootstrap的AndroidElement的映照關(guān)系

我們?cè)谀_本上對(duì)控件的認(rèn)識(shí)就是1個(gè)WebElement:

WebElement addNote = driver.findElementByAndroidUIAutomator("new UiSelector().text("Add note")");
而在Bootstrap中1個(gè)對(duì)象就是1個(gè)AndroidElement. 那末它們是怎樣映照到1起的呢?我們其實(shí)可以先看以下的代碼:

WebElement addNote = driver.findElementByAndroidUIAutomator("new UiSelector().text("Add note")"); addNote.getText(); addNote.click();
做的事情就是取得Notes這個(gè)app的菜單,然后調(diào)用控件的getText來(lái)取得‘Add note'控件的文本信息,和通過(guò)控件的click方法來(lái)點(diǎn)擊該控件。那末我們看下調(diào)試信息是怎樣的:


pc端傳過(guò)來(lái)的json字串有幾個(gè)fields:

  • cmd:代表這個(gè)是甚么命令類(lèi)型,其實(shí)就是AndroidCommandType的那兩個(gè)值
package io.appium.android.bootstrap; /** * Enumeration for all the command types. * */ public enum AndroidCommandType { ACTION, SHUTDOWN }
  • action: 具體命令
  • params: 提供的參數(shù),這里提供了1個(gè)elementId的鍵值對(duì)
從上面的兩條調(diào)試信息看來(lái),其實(shí)沒(méi)有明顯的看到究竟使用的是哪一個(gè)控件。其實(shí)這里不起眼的elementId就是肯定用的是哪一個(gè)控件的,注意這個(gè)elementId其實(shí)不是1個(gè)控件在界面上的資源id,它實(shí)際上是Bootstrap保護(hù)的1個(gè)保存所有已獲得過(guò)的控件的哈希表的鍵值。如上1小節(jié)看到的,每個(gè)AndroidElement都有兩個(gè)重要的成員變量:

  • UiObject el :uiautomator框架中代表了1個(gè)真實(shí)的窗口控件
  • Sting id :  1個(gè)唯1的自動(dòng)增加的字串類(lèi)型整數(shù),pc端就是通過(guò)它來(lái)在AndroidElementHash這個(gè)類(lèi)中找到想要的控件的

3. AndroidElement控件哈希表

上1節(jié)我們說(shuō)到appium pc端是通過(guò)id把WebElement和目標(biāo)機(jī)器真?zhèn)€AndroidElement映照起來(lái)的,那末我們這1節(jié)就來(lái)看下保護(hù)AndroidElement的這個(gè)哈希表是怎樣實(shí)現(xiàn)的。

首先,它具有兩個(gè)成員變量:

private final Hashtable<String, AndroidElement> elements; private Integer counter;
  • elements :1個(gè)以AndroidElement 的id的字串類(lèi)型為key,以AndroidElement的實(shí)例為value的的哈希表
  • counter : 1個(gè)整型變量,有兩個(gè)作用:其1是它代表了當(dāng)前已用到的控件的數(shù)目(其實(shí)也不完全是,你在腳本中對(duì)同1個(gè)控件調(diào)用兩次findElement其實(shí)會(huì)產(chǎn)生兩個(gè)不同id的AndroidElement控件),其2是它代表了1個(gè)新用到的控件的id,而這個(gè)id就是上面的elements哈希表的鍵
這個(gè)哈希表的鍵值都是從0開(kāi)始的,請(qǐng)看它的構(gòu)造函數(shù):
/** * Constructor */ public AndroidElementsHash() { counter = 0; elements = new Hashtable<String, AndroidElement>(); }
而它在全部Bootstrap中是有且只有1個(gè)實(shí)例的,且看它的單例模式實(shí)現(xiàn):
public static AndroidElementsHash getInstance() { if (AndroidElementsHash.instance == null) { AndroidElementsHash.instance = new AndroidElementsHash(); } return AndroidElementsHash.instance; }
以下增加1個(gè)控件的方法addElement充分描寫(xiě)了為何說(shuō)counter是1個(gè)自增加的key,且是每一個(gè)新發(fā)現(xiàn)的AndroidElement控件的id:
public AndroidElement addElement(final UiObject element) { counter++; final String key = counter.toString(); final AndroidElement el = new AndroidElement(key, element); elements.put(key, el); return el; }
從Appium發(fā)過(guò)來(lái)的控件查找命令大方向上分兩類(lèi):
  • 1. 直接基于Appium Driver來(lái)查找,這類(lèi)情況下appium發(fā)過(guò)來(lái)的json命令是不包括控件哈希表的鍵值信息的
[java] view plaincopy
  1. WebElement addNote = driver.findElement(By.name("Add note"));  
  • 2. 基于父控件查找:
[java] view plaincopy
  1. WebElement el = driver.findElement(By.className("android.widget.ListView")).findElement(By.name("Note1"));  
以上的腳本會(huì)先嘗試找到Note1這個(gè)日記的父控件ListView,并把這個(gè)控件保存到控件哈希表,然后再根據(jù)父控件的哈希表鍵值和子控件的選擇子找到想要的Note1:

AndroidElementHash的這個(gè)getElement命令要做的事情就是針對(duì)這兩點(diǎn)來(lái)根據(jù)不同情況取得目標(biāo)控件
[java] view plaincopy
  1. /** 
  2.  * Return an elements child given the key (context id), or uses the selector 
  3.  * to get the element. 
  4.  *  
  5.  * @param sel 
  6.  * @param key 
  7.  *          Element id. 
  8.  * @return {@link AndroidElement} 
  9.  * @throws ElementNotFoundException 
  10.  */  
  11. public AndroidElement getElement(final UiSelector sel, final String key)  
  12.     throws ElementNotFoundException {  
  13.   AndroidElement baseEl;  
  14.   baseEl = elements.get(key);  
  15.   UiObject el;  
  16.   
  17.   if (baseEl == null) {  
  18.     el = new UiObject(sel);  
  19.   } else {  
  20.     try {  
  21.       el = baseEl.getChild(sel);  
  22.     } catch (final UiObjectNotFoundException e) {  
  23.       throw new ElementNotFoundException();  
  24.     }  
  25.   }  
  26.   
  27.   if (el.exists()) {  
  28.     return addElement(el);  
  29.   } else {  
  30.     throw new ElementNotFoundException();  
  31.   }  
  32. }  
  • 如果是第1種情況就直接通過(guò)選擇子構(gòu)建UiObject對(duì)象,然后通過(guò)addElement把UiObject對(duì)象轉(zhuǎn)換成AndroidElement對(duì)象保存到控件哈希表
  • 如果是第2種情況就先根據(jù)appium傳過(guò)來(lái)的控件哈希表鍵值取得父控件,再通過(guò)子控件的選擇子在父控件的基礎(chǔ)上查找到目標(biāo)UiObject控件,最后跟上面1樣把該控件通過(guò)上面的addElement把UiObject控件轉(zhuǎn)換成AndroidElement控件對(duì)象保存到控件哈希表




4. 求證

上面有提過(guò),如果pc真?zhèn)€腳本履行對(duì)同1個(gè)控件的兩次findElement會(huì)創(chuàng)建兩個(gè)不同id的AndroidElement并寄存到控件哈希表中,那末為何appium的團(tuán)隊(duì)沒(méi)有做1個(gè)增強(qiáng),增加1個(gè)keyMap的方法(算法)和1些額外的信息來(lái)讓同1個(gè)控件使用不同的key的時(shí)候?qū)?yīng)的還是同1個(gè)AndroidElement控件呢?畢竟這才是哈希表實(shí)用的特性之1了,不然你直接用1個(gè)Dictionary不就完事了?網(wǎng)上說(shuō)了幾點(diǎn)hashtable和dictionary的差別,如多線程環(huán)境最好使用哈希表而非字典等,但在bootstrap這個(gè)控件哈希表的情況下我不是很佩服這些說(shuō)法,有誰(shuí)清楚的還勞煩指導(dǎo)12了
這里至于為何appium不去提供額外的key信息并且實(shí)現(xiàn)keyMap算法,我個(gè)人倒是認(rèn)為有以下緣由:
  • 有誰(shuí)這么無(wú)聊在同1個(gè)測(cè)試方法中對(duì)同1個(gè)控件查找兩次?
  • 如果同1個(gè)控件應(yīng)用不同的選擇子查找兩次的話,由于終究底層的UiObject的成員變量UiSelector mSelector不1樣,所以確切可以認(rèn)為是不同的控件
但以下兩個(gè)如果用一樣的UiSelector選擇子來(lái)查找控件的情況我就解析不了了,畢竟在我看來(lái)bootstrap這邊應(yīng)當(dāng)把它們看成是同1個(gè)對(duì)象的:
  • 同1個(gè)腳本不同的方法中分別對(duì)同1控件用一樣的UiSelelctor選擇子進(jìn)行查找呢?
  • 不同腳本中呢?
這些或許在今后深入了解中得到解決,但看家如果知道的,還望不吝賜教

5. 小結(jié)

最后我們對(duì)bootstrap的控件相干知識(shí)點(diǎn)做1個(gè)總結(jié)
  • AndroidElement的1個(gè)實(shí)例代表了1個(gè)bootstrap的控件
  • AndroidElement控件的成員變量UiObject el代表了uiautomator框架中的1個(gè)真實(shí)窗口控件,通過(guò)它就能夠直接透過(guò)uiautomator框架對(duì)控件進(jìn)行實(shí)質(zhì)性操作
  • pc真?zhèn)€WebElement元素和Bootstrap的AndroidElement控件是通過(guò)AndroidElement控件的String id進(jìn)行映照關(guān)聯(lián)的
  • AndroidElementHash類(lèi)保護(hù)了1個(gè)以AndroidElement的id為鍵值,以AndroidElement的實(shí)例為value的全局唯1哈希表,pc端想要取得1個(gè)控件的時(shí)候會(huì)先從這個(gè)哈希表查找,如果沒(méi)有了再創(chuàng)建新的AndroidElement控件并加入到該哈希表中,所以該哈希表中保護(hù)的是1個(gè)當(dāng)前已使用過(guò)的控件
生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 日本三级网址 | 亚洲高清电影 | 日韩精品久久一区二区三区 | 欧美一区二区三区婷婷月色 | 精品一区中文字幕 | 国产伦精品一区二区三区免费迷 | 亚洲第十页 | 日韩高清在线免费观看 | 国产在线不卡视频 | 欧美一区二区三区 | 黄色片免费看 | 亚洲免费网站 | 黄色伊人网 | 成人福利 | 亚洲日本va中文字幕久久 | 国产一二区在线 | 日本免费黄色片 | 久久成人综合 | 日韩视频在线观看 | 色淫视频 | av天天干 | 欧美极品一区二区三区 | 成人av播放| 99久久毛片免费观看 | 国产女主播在线视频 | 中文字幕av第一页 | 欧美区一区二 | 最新精品在线 | 精品久久久久一区二区国产 | 一区二区日韩精品 | 国产剧情一区二区三区 | 日韩精品极品视频在线观看免费 | av在线不卡免费 | 自拍偷拍福利视频 | 香蕉视频成年人 | 欧洲亚洲一区二区三区四区五区 | 日韩精品中文字幕一区二区 | 性一级毛片 | 成人福利在线观看 | 欧美综合视频 | 日韩免费一区 |