• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            專(zhuān)職C++

            不能停止的腳步

              C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
              163 Posts :: 7 Stories :: 135 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(28)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            使用appium輸入中文,發(fā)現(xiàn)好慢!至少5秒以上,如果在這樣的情況下做測(cè)試,這就好悲劇了。 
            從appium(1.6.3)代碼上來(lái)看,沒(méi)有什么問(wèn)題,直接是通過(guò)boostrap的setText的方法。說(shuō)是就下載了appium-bootstrap的代碼看,從這里開(kāi)發(fā)找到的代碼,都是java的代碼,找到 io.appium.android.bootstrap.handler.SetText 
            在new Clear().execute(command);時(shí)間長(zhǎng)達(dá)5秒(打日志發(fā)現(xiàn)),不管文本框有沒(méi)有內(nèi)容,都會(huì)執(zhí)行
            /*
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * See the NOTICE file distributed with this work for additional
             * information regarding copyright ownership.
             * You may obtain a copy of the License at
             *
             *     
            http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             
            */

            package io.appium.android.bootstrap.handler;

            import com.android.uiautomator.core.UiDevice;
            import com.android.uiautomator.core.UiObjectNotFoundException;
            import com.android.uiautomator.core.UiSelector;
            import io.appium.android.bootstrap.*;
            import io.appium.android.bootstrap.exceptions.ElementNotFoundException;
            import io.appium.android.bootstrap.handler.Find;
            import org.json.JSONException;

            import java.util.Hashtable;

            /**
             * This handler is used to set text in elements that support it.
             *
             
            */
            public class SetText extends CommandHandler {

              /*
               * @param command The {@link AndroidCommand} used for this handler.
               *
               * @return {@link AndroidCommandResult}
               *
               * @throws JSONException
               *
               * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android.
               * bootstrap.AndroidCommand)
               
            */
              @Override
              public AndroidCommandResult execute(final AndroidCommand command)
                  throws JSONException {
                AndroidElement el = null;
                if (command.isElementCommand()) {
                  el = command.getElement();
                  Logger.debug("Using element passed in: " + el.getId());
                } else {
                  try {
                    AndroidElementsHash  elements = AndroidElementsHash.getInstance();
                    el = elements.getElement(new UiSelector().focused(true), "");
                    Logger.debug("Using currently-focused element: " + el.getId());
                  } catch (ElementNotFoundException e) {
                    Logger.debug("Error retrieving focused element: " + e);
                    return getErrorResult("Unable to set text without a focused element.");
                  }
                }
                try {
                  final Hashtable<String, Object> params = command.params();
                  boolean replace = Boolean.parseBoolean(params.get("replace").toString());
                  String text = params.get("text").toString();
                  boolean pressEnter = false;
                  if (text.endsWith("\\n")) {
                    pressEnter = true;
                    text = text.replace("\\n", "");
                    Logger.debug("Will press enter after setting text");
                  }
                  boolean unicodeKeyboard = false;
                  if (params.get("unicodeKeyboard") != null) {
                    unicodeKeyboard = Boolean.parseBoolean(params.get("unicodeKeyboard").toString());
                  }
                  String currText = el.getText();
                  new Clear().execute(command); //不管有沒(méi)有,這里都會(huì)執(zhí)行
                  if (!el.getText().isEmpty()) {
                    // clear could have failed, or we could have a hint in the field
                    
            // we'll assume it is the latter
                    Logger.debug("Text not cleared. Assuming remainder is hint text.");
                    currText = "";
                  }
                  if (!replace) {
                    text = currText + text;
                  }
                  final boolean result = el.setText(text, unicodeKeyboard);
                  if (!result) {
                    return getErrorResult("el.setText() failed!");
                  }
                  if (pressEnter) {
                    final UiDevice d = UiDevice.getInstance();
                    d.pressEnter();
                  }
                  return getSuccessResult(result);
                } catch (final UiObjectNotFoundException e) {
                  return new AndroidCommandResult(WDStatus.NO_SUCH_ELEMENT,
                      e.getMessage());
                } catch (final Exception e) { // handle NullPointerException
                  return getErrorResult("Unknown error");
                }
              }
            }
            然后,我們?cè)倏碈lear的代碼

            /*
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * See the NOTICE file distributed with this work for additional
             * information regarding copyright ownership.
             * You may obtain a copy of the License at
             *
             *     
            http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
             
            */

            package io.appium.android.bootstrap.handler;

            import android.graphics.Rect;
            import android.os.SystemClock;
            import android.view.InputDevice;
            import android.view.KeyCharacterMap;
            import android.view.KeyEvent;
            import com.android.uiautomator.core.UiObject;
            import com.android.uiautomator.core.UiObjectNotFoundException;
            import com.android.uiautomator.core.UiSelector;
            import io.appium.android.bootstrap.AndroidCommand;
            import io.appium.android.bootstrap.AndroidCommandResult;
            import io.appium.android.bootstrap.AndroidElement;
            import io.appium.android.bootstrap.CommandHandler;
            import io.appium.android.bootstrap.Logger;
            import io.appium.android.bootstrap.WDStatus;
            import io.appium.uiautomator.core.InteractionController;
            import io.appium.uiautomator.core.UiAutomatorBridge;
            import org.json.JSONException;

            import java.lang.reflect.InvocationTargetException;

            /**
             * This handler is used to clear elements in the Android UI.
             *
             * Based on the element Id, clear that element.
             *
             * UiAutomator method clearText is flaky hence overriding it with custom implementation.
             
            */
            public class Clear extends CommandHandler {

              /*
               * Trying to select entire text with correctLongClick and increasing time intervals.
               * Checking if element still has text in them and and if true falling back on UiAutomator clearText
               *
               * @param command The {@link AndroidCommand}
               *
               * @return {@link AndroidCommandResult}
               *
               * @throws JSONException
               *
               * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android.
               * bootstrap.AndroidCommand)
               
            */
              @Override
              public AndroidCommandResult execute(final AndroidCommand command)
                      throws JSONException {
                if (command.isElementCommand()) {
                  try {
                    final AndroidElement el = command.getElement();

                    // first, try to do native clearing
                    Logger.debug("Attempting to clear using UiObject.clearText().");
                    el.clearText();  //無(wú)條件都會(huì)執(zhí)行這塊。然后再分析clearText
                    if (el.getText().isEmpty()) {
                      return getSuccessResult(true);
                    }

                    // see if there is hint text
                    if (hasHintText(el)) {
                      Logger.debug("Text remains after clearing, "
                          + "but it appears to be hint text.");
                      return getSuccessResult(true);
                    }

                    // next try to select everything and delete
                    Logger.debug("Clearing text not successful. Attempting to clear " +
                            "by selecting all and deleting.");
                    if (selectAndDelete(el)) {
                      return getSuccessResult(true);
                    }

                    // see if there is hint text
                    if (hasHintText(el)) {
                      Logger.debug("Text remains after clearing, "
                          + "but it appears to be hint text.");
                      return getSuccessResult(true);
                    }

                    // finally try to send delete keys
                    Logger.debug("Clearing text not successful. Attempting to clear " +
                            "by sending delete keys.");
                    if (sendDeleteKeys(el)) {
                      return getSuccessResult(true);
                    }

                    if (!el.getText().isEmpty()) {
                      // either there was a failure, or there is hint text
                      if (hasHintText(el)) {
                        Logger.debug("Text remains after clearing, " +
                                "but it appears to be hint text.");
                        return getSuccessResult(true);
                      } else if (!el.getText().isEmpty()) {
                        Logger.debug("Exhausted all means to clear text but '" +
                                el.getText() + "' remains.");
                        return getErrorResult("Clear text not successful.");
                      }
                    }
                    return getSuccessResult(true);
                  } catch (final UiObjectNotFoundException e) {
                    return new AndroidCommandResult(WDStatus.NO_SUCH_ELEMENT,
                        e.getMessage());
                  } catch (final Exception e) { // handle NullPointerException
                    return getErrorResult("Unknown error clearing text");
                  }
                }
                return getErrorResult("Unknown error");
              }

              private boolean selectAndDelete(AndroidElement el)
                  throws UiObjectNotFoundException, IllegalAccessException,
                    InvocationTargetException, NoSuchMethodException {
                Rect rect = el.getVisibleBounds();
                // Trying to select entire text.
                TouchLongClick.correctLongClick(rect.left + 20, rect.centerY(), 2000);
                UiObject selectAll = new UiObject(new UiSelector().descriptionContains("Select all"));
                if (selectAll.waitForExists(2000)) {
                  selectAll.click();
                }
                // wait for the selection
                SystemClock.sleep(500);
                // delete it
                UiAutomatorBridge.getInstance().getInteractionController().sendKey(KeyEvent.KEYCODE_DEL, 0);

                return el.getText().isEmpty();
              }

              private boolean sendDeleteKeys(AndroidElement el)
                  throws UiObjectNotFoundException, IllegalAccessException,
                    InvocationTargetException, NoSuchMethodException {
                String tempTextHolder = "";

                // Preventing infinite while loop.
                while (!el.getText().isEmpty() && !tempTextHolder.equalsIgnoreCase(el.getText())) {
                  // Trying send delete keys after clicking in text box.
                  el.click();
                  // Sending delete keys asynchronously, both forward and backward
                  for (int key : new int[] { KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_FORWARD_DEL }) {
                    tempTextHolder = el.getText();
                    final int length = tempTextHolder.length();
                    final long eventTime = SystemClock.uptimeMillis();
                    KeyEvent deleteEvent = new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN,
                            key, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0,
                            InputDevice.SOURCE_KEYBOARD);
                    for (int count = 0; count < length; count++) {
                      UiAutomatorBridge.getInstance().injectInputEvent(deleteEvent, false);
                    }
                  }
                }

                return el.getText().isEmpty();
              }

              private boolean hasHintText(AndroidElement el)
                  throws UiObjectNotFoundException, IllegalAccessException,
                    InvocationTargetException, NoSuchMethodException {
                // to test if the remaining text is hint text, try sending a single
                
            // delete key and testing if there is any change.
                
            // ignore the off-chance that the delete silently fails and we get a false
                
            // positive.
                String currText = el.getText();

                try {
                  if (!el.getBoolAttribute("focused")) {
                    Logger.debug("Could not check for hint text because the element is not focused!");
                    return false;
                  }
                } catch (final Exception e) {
                  Logger.debug("Could not check for hint text: " + e.getMessage());
                  return false;
                }

                InteractionController interactionController = UiAutomatorBridge.getInstance().getInteractionController();
                interactionController.sendKey(KeyEvent.KEYCODE_DEL, 0);
                interactionController.sendKey(KeyEvent.KEYCODE_FORWARD_DEL, 0);

                return currText.equals(el.getText());
              }
            }
            再看看AndroidElement.clearText是什么樣的
              public void clearText() throws UiObjectNotFoundException {
                el.clearTextField();
              }
            這個(gè)都就是com.android.uiautomator.core.UiObject.clearTextField 
            于是找再找到uiautomator的代碼再來(lái)分析(這個(gè)代碼需要下載andriod sdk,在對(duì)應(yīng)android版本的目錄下,會(huì)有源碼,也有uiautomator的源代碼),我這里的路徑是: 
            Android\sdk\sources\android-19\com\android\uiautomator\core 
            在UiObject.java找到clearTextField實(shí)現(xiàn)
            /**
                 * Clears the existing text contents in an editable field.
                 *
                 * The {
            @link UiSelector} of this object must reference a UI element that is editable.
                 *
                 * When you call this method, the method first sets focus at the start edge of the field.
                 * The method then simulates a long-press to select the existing text, and deletes the
                 * selected text.
                 *
                 * If a "Select-All" option is displayed, the method will automatically attempt to use it
                 * to ensure full text selection.
                 *
                 * Note that it is possible that not all the text in the field is selected; for example,
                 * if the text contains separators such as spaces, slashes, at symbol etc.
                 * Also, not all editable fields support the long-press functionality.
                 *
                 * 
            @throws UiObjectNotFoundException
                 * 
            @since API Level 16
                 
            */
                public void clearTextField() throws UiObjectNotFoundException {
                    Tracer.trace();
                    // long click left + center
                    AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
                    if(node == null) {
                        throw new UiObjectNotFoundException(getSelector().toString());
                    }
                    Rect rect = getVisibleBounds(node);
                    getInteractionController().longTapNoSync(rect.left + 20, rect.centerY()); //長(zhǎng)按
                    
            // check if the edit menu is open
                    UiObject selectAll = new UiObject(new UiSelector().descriptionContains("Select all"));
                    if(selectAll.waitForExists(50))
                        selectAll.click();
                    // wait for the selection
                    SystemClock.sleep(250); //這里等250ms
                    
            // delete it
                    getInteractionController().sendKey(KeyEvent.KEYCODE_DEL, 0);
                }
            相信大家,可以找到慢的原因了。這里做一次長(zhǎng)按,然再再做全選,然后再sleep(250),還有一個(gè)selectAll.waitForExists(50), 這些都是耗費(fèi)時(shí)間的。
            再找一下UiObject.java中setText的實(shí)現(xiàn)

                public boolean setText(String text) throws UiObjectNotFoundException {
                    Tracer.trace(text);
                    clearTextField();
                    return getInteractionController().sendText(text);
                }
            發(fā)現(xiàn)這里又調(diào)用了一次clearTextField,這樣算來(lái),設(shè)一次文本,都會(huì)清理兩次文本,于是,這時(shí)間就長(zhǎng)了。 
            優(yōu)化:只需要將io.appium.android.bootstrap.handler.SetText中的new Clear().execute(command)去掉就可以了。

            posted on 2017-05-27 17:35 冬瓜 閱讀(1877) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 原創(chuàng)appium
            久久精品国产第一区二区三区| 久久热这里只有精品在线观看| 99久久精品免费看国产一区二区三区| 亚洲成人精品久久| 久久er99热精品一区二区| 97精品伊人久久久大香线蕉| 午夜精品久久久久成人| 国产精品激情综合久久| 国产免费福利体检区久久| 久久精品国产亚洲一区二区| 嫩草伊人久久精品少妇AV| 色偷偷88888欧美精品久久久| 久久天天躁狠狠躁夜夜不卡| 亚洲精品无码久久久| 日韩AV毛片精品久久久| 亚洲国产日韩综合久久精品| 久久成人小视频| 欧美喷潮久久久XXXXx| 久久久久久国产精品无码超碰| 人妻丰满AV无码久久不卡| 久久久久久久久久久久中文字幕 | 亚洲精品美女久久久久99| 人妻无码中文久久久久专区| 777米奇久久最新地址| 青青草国产成人久久91网| 精品国产综合区久久久久久| 亚洲精品综合久久| 久久久免费精品re6| 99久久精品无码一区二区毛片| 久久精品国产精品亚洲| 伊人精品久久久久7777| 亚洲色大成网站WWW久久九九| 亚洲精品无码久久一线| 久久久久人妻精品一区 | 久久精品成人免费网站| 久久综合久久性久99毛片| 亚洲精品国产综合久久一线| 久久国产亚洲精品| 久久天天躁狠狠躁夜夜躁2O2O| 久久国产免费观看精品3| 国产精品对白刺激久久久|