Android 查找布局是否具有特定的文本视图

Android 查找布局是否具有特定的文本视图,android,selenium,appium,selendroid,Android,Selenium,Appium,Selendroid,我有这样的线性布局: List<WebElement> allFieldsInLayout = driver.findElements(By.id("com.flipkart.android:id/product_list_product_item_layout")); List<WebElement> allTitlesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipka

我有这样的线性布局:

List<WebElement> allFieldsInLayout = driver.findElements(By.id("com.flipkart.android:id/product_list_product_item_layout"));
List<WebElement> allTitlesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_main_text']"));
List<WebElement> allsubTitlesOnCurrentScreen   = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_sub_text']"));
List<WebElement> allOfferPricesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_price']"));
List<WebElement> allListPriceOnCurrentScreen   = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_mrp']"));
for(int i=0;i<allFieldsInLayout.size();i++){
            List<WebElement> allElementsinCurrentLayout = allFieldsInLayout.get(i).findElements(By.xpath("//android.widget.RelativeLayout[@index='2']"));
            for(int j=0;j<allElementsinCurrentLayout.size();j++) {
                System.out.println("Layout " + allElementsinCurrentLayout.get(j));
            }
}

现在有些线性布局有子类别,有些没有子类别。同样的,有些有折扣,有些没有

所以当我这样做的时候:

List<WebElement> allFieldsInLayout = driver.findElements(By.id("com.flipkart.android:id/product_list_product_item_layout"));
List<WebElement> allTitlesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_main_text']"));
List<WebElement> allsubTitlesOnCurrentScreen   = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_sub_text']"));
List<WebElement> allOfferPricesOnCurrentScreen = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_price']"));
List<WebElement> allListPriceOnCurrentScreen   = driver.findElements(By.xpath("//*[@resource-id='com.flipkart.android:id/product_list_product_item_mrp']"));
for(int i=0;i<allFieldsInLayout.size();i++){
            List<WebElement> allElementsinCurrentLayout = allFieldsInLayout.get(i).findElements(By.xpath("//android.widget.RelativeLayout[@index='2']"));
            for(int j=0;j<allElementsinCurrentLayout.size();j++) {
                System.out.println("Layout " + allElementsinCurrentLayout.get(j));
            }
}

如果我没有相应的子标题或者没有折扣,我想在我的列表中为空。如何做?

一般来说,我处理此类问题的方法是找到包含单个产品所有产品信息的最顶层元素。将这些元素作为集合返回,并对其进行迭代。在每个迭代中,查找包含元素的不同信息。。。检查是否存在并获取数据(如果存在)。此方法允许您将每个产品的所有属性/数据整齐地捕获为一个包

您的方法存在的问题是,您将数据元素(例如字幕)与产品分开存储。因此,想象一下,如果你的页面上有4个产品,其中只有2个有字幕。你循环浏览4个产品(按索引)访问字幕。。。您将有2个问题:1)您将运行字幕数组的末尾,因为只有2个,而您正在循环到4个。2) 您的字幕数组与产品数组中的产品不匹配

想象这是你的页面

Product1
Subtitle1

Product2

Product3
Subtitle3

Product4
您的产品数组将包含:Product1、Product2、Product3、Product4

您的字幕数组将包含:字幕1,字幕3

因此,当您使用产品索引循环时,您将得到:

Product1, Subtitle1
Product2, Subtitle3 // notice the mismatch 2 and 3
Product3, Array out of index error
因此,您用完了字幕数组的末尾,并且您的字幕与相应的产品不匹配。希望这个例子更有意义

不管怎样,我是这样做的。我没有手机应用程序,所以我去flipkart.com搜索翻盖,并编写下面的代码来演示我所说的内容。这段代码有效,我只是运行了它

public static void main(String[] args)
{
    WebDriver driver = new FirefoxDriver();
    driver.manage().window().maximize();
    driver.get("http://www.flipkart.com/search?q=flip+cover&as=on&as-show=on&otracker=start&as-pos=4_q_flip+cover&sid=search.flipkart.com&storePath=search.flipkart.com&type=pr&redirectToResponseURL=false&redirection=true&isMsiteTraffic=1");
    List<Product> products = new ArrayList<>(); // List of Product type that will contain each product on the page
    List<WebElement> productContainers = driver.findElements(By.cssSelector("div.gd-col.gu3")); // the outermost element that contains all data related to a given product
    // loop through the product container elements and extract each bit of data that we care about
    for (WebElement productContainer : productContainers)
    {
        String name = productContainer.findElement(By.cssSelector("a[data-tracking-id='prd_title']")).getText().trim();
        String ratingStars = ""; // we have to initialize these variables at this scope so we can access them later outside the IF below
        String NoOfRatings = ""; // NOTE: if a rating does not exist for this product, ratingStars and NoOfRatings will be empty string, ""
        // these next two lines are how we determine if a piece of data exists... get the element using .findElements...
        List<WebElement> ratingContainer = productContainer.findElements(By.cssSelector("div.pu-rating"));
        // ... and then check to see if the list is empty
        if (!ratingContainer.isEmpty())
        {
            // ratings exist for this product, grab the relevant data
            WebElement rating = ratingContainer.get(0).findElement(By.cssSelector("div.fk-stars-small"));
            ratingStars = rating.getAttribute("title"); // product rating in stars
            NoOfRatings = ratingContainer.get(0).getText().trim(); // the total number of ratings, you can parse this string and extract the number, if desired
        }
        String finalPrice = productContainer.findElement(By.cssSelector("div.pu-final")).getText().trim(); // the price, you can extract the number, if desired
        products.add(new Product(name, finalPrice, ratingStars, NoOfRatings)); // add all the relevant data into a nice, neat package just for this one product
    }

    // dumps the data for the products on the page
    for (Product product : products)
    {
        System.out.println("Product: " + product.name);
        System.out.println("Rating: " + product.ratingStars);
        System.out.println("Number of ratings: " + product.NoOfRatings);
        System.out.println("Final price: " + product.finalPrice);
        System.out.println("-----------------------------");
    }
}

// this class holds just 4 bits of data for each product, you can obviously add more to the class if you want to store more data
public static class Product
{
    public String name;
    public String finalPrice;
    public String ratingStars;
    public String NoOfRatings;

    public Product(String name, String finalPrice, String ratingStars, String NoOfRatings)
    {
        this.name = name;
        this.finalPrice = finalPrice;
        this.ratingStars = ratingStars;
        this.NoOfRatings = NoOfRatings;
    }
}

通常,我处理此类问题的方法是找到包含单个产品的所有产品信息的最顶层元素。将这些元素作为集合返回,并对其进行迭代。在每个迭代中,查找包含元素的不同信息。。。检查是否存在并获取数据(如果存在)。此方法允许您将每个产品的所有属性/数据整齐地捕获为一个包

您的方法存在的问题是,您将数据元素(例如字幕)与产品分开存储。因此,想象一下,如果你的页面上有4个产品,其中只有2个有字幕。你循环浏览4个产品(按索引)访问字幕。。。您将有2个问题:1)您将运行字幕数组的末尾,因为只有2个,而您正在循环到4个。2) 您的字幕数组与产品数组中的产品不匹配

想象这是你的页面

Product1
Subtitle1

Product2

Product3
Subtitle3

Product4
您的产品数组将包含:Product1、Product2、Product3、Product4

您的字幕数组将包含:字幕1,字幕3

因此,当您使用产品索引循环时,您将得到:

Product1, Subtitle1
Product2, Subtitle3 // notice the mismatch 2 and 3
Product3, Array out of index error
因此,您用完了字幕数组的末尾,并且您的字幕与相应的产品不匹配。希望这个例子更有意义

不管怎样,我是这样做的。我没有手机应用程序,所以我去flipkart.com搜索翻盖,并编写下面的代码来演示我所说的内容。这段代码有效,我只是运行了它

public static void main(String[] args)
{
    WebDriver driver = new FirefoxDriver();
    driver.manage().window().maximize();
    driver.get("http://www.flipkart.com/search?q=flip+cover&as=on&as-show=on&otracker=start&as-pos=4_q_flip+cover&sid=search.flipkart.com&storePath=search.flipkart.com&type=pr&redirectToResponseURL=false&redirection=true&isMsiteTraffic=1");
    List<Product> products = new ArrayList<>(); // List of Product type that will contain each product on the page
    List<WebElement> productContainers = driver.findElements(By.cssSelector("div.gd-col.gu3")); // the outermost element that contains all data related to a given product
    // loop through the product container elements and extract each bit of data that we care about
    for (WebElement productContainer : productContainers)
    {
        String name = productContainer.findElement(By.cssSelector("a[data-tracking-id='prd_title']")).getText().trim();
        String ratingStars = ""; // we have to initialize these variables at this scope so we can access them later outside the IF below
        String NoOfRatings = ""; // NOTE: if a rating does not exist for this product, ratingStars and NoOfRatings will be empty string, ""
        // these next two lines are how we determine if a piece of data exists... get the element using .findElements...
        List<WebElement> ratingContainer = productContainer.findElements(By.cssSelector("div.pu-rating"));
        // ... and then check to see if the list is empty
        if (!ratingContainer.isEmpty())
        {
            // ratings exist for this product, grab the relevant data
            WebElement rating = ratingContainer.get(0).findElement(By.cssSelector("div.fk-stars-small"));
            ratingStars = rating.getAttribute("title"); // product rating in stars
            NoOfRatings = ratingContainer.get(0).getText().trim(); // the total number of ratings, you can parse this string and extract the number, if desired
        }
        String finalPrice = productContainer.findElement(By.cssSelector("div.pu-final")).getText().trim(); // the price, you can extract the number, if desired
        products.add(new Product(name, finalPrice, ratingStars, NoOfRatings)); // add all the relevant data into a nice, neat package just for this one product
    }

    // dumps the data for the products on the page
    for (Product product : products)
    {
        System.out.println("Product: " + product.name);
        System.out.println("Rating: " + product.ratingStars);
        System.out.println("Number of ratings: " + product.NoOfRatings);
        System.out.println("Final price: " + product.finalPrice);
        System.out.println("-----------------------------");
    }
}

// this class holds just 4 bits of data for each product, you can obviously add more to the class if you want to store more data
public static class Product
{
    public String name;
    public String finalPrice;
    public String ratingStars;
    public String NoOfRatings;

    public Product(String name, String finalPrice, String ratingStars, String NoOfRatings)
    {
        this.name = name;
        this.finalPrice = finalPrice;
        this.ratingStars = ratingStars;
        this.NoOfRatings = NoOfRatings;
    }
}

为什么使用此方法查找每个项目?根据每个项目的ID(或名称、标签等)查找每个项目可能更容易,如果您在这里查找,它可以找到不同的方法。@GastonF。你说的是哪种方法?有一些示例使用findViewById。按资源名称查找。其他方法。@GastonF。我正在使用Appium Frameworkek,我发现您的代码中有问题,您正在迭代所有标题OnCurrentScreen,但尝试获取值​​allListPriceOnCurrentScreen具有相同的索引,也许您的代码应该类似于为什么使用此方法查找每个项目?根据每个项目的ID(或名称、标签等)查找每个项目可能更容易,如果您在这里查找,它可以找到不同的方法。@GastonF。你说的是哪种方法?有一些示例使用findViewById。按资源名称查找。其他方法。@GastonF。我正在使用Appium Frameworkek,我发现您的代码中有问题,您正在迭代所有标题OnCurrentScreen,但尝试获取值​​allListPriceOnCurrentScreen具有相同的索引,也许您的代码应该如下所示