Appium Android Bootstrap Source Analysis control androidelement

Source: Internet
Author: User
Tags appium

Through the previous article "Appium Android Bootstrap Source Analysis " We have a preliminary understanding of the definition of bootstrap and its location in Appium and Uiautomator, So according to the normal way of writing the book, the next chapter should be to see how bootstrap set up the socket to get the data and how to deal with it. But I don't think this is going to be very good, because the whole article is going to be very lengthy, because you're in the process of writing a class that you don't know and you jump in to explain it. Here I think we should try to learn from the famous "refactoring" the proposal of the book: A method of code should not be written too long, otherwise the readability will be very poor, as far as possible to break it down into different functions. Then we are here to use a similar idea, do not try to get everything done in an article, but try to first the key class to describe clearly, and finally go to the class through an example analysis to the string presented to the reader, so that we do not because an article too long affect readability and give up learning.

So why do we first say bootstrap the handle to the control instead of the socket-related socket server you just mentioned? I look like this, you see I this article, it is possible to know before I uiautomator the source for the analysis of the series of articles, or already have uiautomator related knowledge, So the head will be more urgent to know how appium is the use of uiautomator, then in Appium in this problem is the most appropriate appium on the server side is how to use the Uiautomator control.

Here we will mainly analyze two classes:

    • androidelement: A class that represents the control of a UI interface held by Bootstrap, which has a UIObject member object and a string member variable ID that represents its key value in the following hash table
    • Androidelementshash: holds a hash table containing all the controls that bootstrap (that is, appium) have seen (that is, the Findelement method found in the script code). Its key is the ID in androidelement, every time Appium find a new control through findelement this ID will +1,appium both the PC and the bootstrap will hold the ID key value of the control, When you need to invoke a control's method, you need to pass the ID key value representing the control so that bootstrap can find the corresponding control from this hash table.

1. The combination of androidelement and UIObject from the above description we can know that androidelement this class has a uiobject this variable:
public class Androidelement {  private final UiObject el;  private String         ID;  ...}
As we all know, UIObject is actually the class that represents a control in Uiautomator, which allows you to manipulate the control (and ultimately, the uiautomation framework). Anroidelement is the way it's going to relate to uiautomator. We can see that the click Method of the following androidelement is really simply called the UIObject's click Method:
  public Boolean click () throws Uiobjectnotfoundexception {    return El.click ();  }
Of course there are many control-related operations here, such as Dragto,gettext,longclick, and so on, but no exception, all through the uiobject to achieve, here is not listed.
2. Mapping of Webelement and bootstrap androidelement of scripts

Our understanding of the control on the script is a webelement:

Webelement addnote =  driver.findelementbyandroiduiautomator ("New Uiselector (). Text (\" Add note\ ")");
And in Bootstrap, an object is a androidelement. So how do they map together? We can actually look at the following code first:

        Webelement addnote = Driver.findelementbyandroiduiautomator ("New Uiselector (). Text (\" Add note\ ")");        Addnote.gettext ();        Addnote.click ();
The thing to do is to get a menu of the Notes app, then call the control's gettext to get the text information of the ' ADD note ' control, and click the control by clicking it. So let's look at the debug information:


The JSON string that comes over the PC has several fields:

    • CMD: What is this command type, which is actually the two values of Androidcommandtype
Package io.appium.android.bootstrap;/** * Enumeration for all the command types. *  */public enum Androidcommandtype {  ACTION, SHUTDOWN}
    • Action: Specific command
    • Params: Provides the parameters, here is a ElementID key value pair
From the above two debugging information, it is not obvious to see what the control is actually used. In fact, the humble elementid is to determine which control is used, note that this elementid is not a control on the interface of the resource ID, it is actually bootstrap maintenance of a saved all the control of the hash table key value. As seen in the previous section, each androidelement has two important member variables:

    • UiObject El : The Uiautomator frame represents a real window control
    • Sting ID : A unique, automatically incremented string type Integer that the PC side uses to find the desired control in the Androidelementhash class.

3. androidelement Control Hash Table

In the previous section we said that the Appium PC side is mapped by the ID of the webelement and target machine side androidelement, then we will look at how to maintain the androidelement of this hash table is how to implement.

First, it has two member variables:

  Private final hashtable<string, androidelement> elements;  Private       Integer                           counter;
    • Elements : a hash table with the Androidelement ID of the string type key, with the instance of Androidelement as value
    • Counter : An integer variable that has two functions: one is that it represents the number of controls currently in use (not exactly, You call two times in the script for the same control findelement actually produces two different IDs of the Androidelement control, and the second is that it represents the ID of a newly used control, and this ID is the key of the elements hash table above.
The key value for this hash table starts at 0, see its constructor:
  /**   * Constructor   *  /Public Androidelementshash () {    counter = 0;    elements = new hashtable<string, androidelement> ();  }
And it has only one instance in the whole bootstrap, and its singleton mode is implemented as follows:
  public static Androidelementshash getinstance () {    if (androidelementshash.instance = = null) {      Androidelementshash.instance = new Androidelementshash ();    }    return androidelementshash.instance;  }
The following method of adding a control addelement fully describes why counter is a self-increasing key, and is the ID of each newly discovered Androidelement control:
  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;  }

The following method GetElement demonstrates whether to take a policy from a hash table or to establish a new control when you want to use a child control of a androidelement control that matches a specified selection to a specified key:
/** * Return an elements child given the key (context ID), or uses the selector * to G   ET the element.   * * @param sel * @param key * Element ID. * @return {@link androidelement} * @throws elementnotfoundexception */public androidelement getelement (final Uiselec    Tor Sel, final String key) throws elementnotfoundexception {androidelement baseel;    Baseel = Elements.get (key);    UiObject el;    if (Baseel = = null) {el = new UiObject (SEL);      } else {try {el = baseel.getchild (SEL);      } catch (Final Uiobjectnotfoundexception e) {throw new elementnotfoundexception ();    }} if (El.exists ()) {return addelement (EL);    } else {throw new elementnotfoundexception (); }  }
    • First, try to get the parent control of the target control from the control hash table by using the ElementID passed from the PC as the key value.
    • Even if the parent control does not exist in the control hash table, create an instance of the UIObject control directly from the selection sub-sel and check that it exists on the interface and then add it to the control hash table
    • If a parent control is found in the hash table, the UIObject instance of the target child control is found based on the control and the sub-sel is selected, as well as if the control exists on the interface and is added to the hash table

4. As mentioned above, if the PC-side script executes two times for the same control findelement will create two different IDs of Androidelement and put into the control hash table, then why Appium's team did not make an enhancement, Add a Keymap method (algorithm) and some additional information to make the same control use a different key or the same androidelement control? After all, this is one of the useful features of the hash table, or you just use a dictionary not to be finished? Online said several Hashtable and dictionary differences, such as multi-threaded environment is best to use a hash table rather than a dictionary, but in the case of bootstrap this control hashtable I am not very convinced of these statements, Who knows what to do with the twos here as to why Appium not to provide additional key information and implement the KEYMAP algorithm, I personally think there are the following reasons:
    • Who's so bored? Find the same control two times in the same test method?
    • If the same control uses a different selection sub-lookup two times, because the final underlying UIOBJECT member variable Uiselector mselector is not the same, it can be considered a different control
But the following two if you use the same uiselector to find the control of the situation I can not parse, after all, in my opinion bootstrap this side should be regarded as the same object:
    • Different methods of the same script are used to find the same control with the same uiselelctor selection?
    • What about the different scripts?
These may be in-depth understanding in the future to be resolved, but housekeeping if you know, but also hope to enlighten
5. Summary Finally, we make a summary of the control-related knowledge points of bootstrap.
    • An instance of Androidelement represents a bootstrap control
    • The member variable of the Androidelement control UIObject el represents a real window control in the Uiautomator framework that allows the control to be substantively manipulated directly through the Uiautomator framework.
    • The webelement element on the PC side and the bootstrap androidelement control are mapped by the string ID of the Androidelement control.
    • The Androidelementhash class maintains a globally unique hash table with the Androidelement ID as the key value, with the instance of Androidelement as the value, and when the PC wants to get a control, it looks from this hash table first. If you do not create a new androidelement control and add it to the hash table, the hash table maintains a control that is currently in use







Appium Android Bootstrap Source Analysis control androidelement

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.