下集预告:
android 借助AccessibilityService实现模拟点击功能-实现重复功能代码复用的架构(五)
本篇分析对一个列表循环执行一个功能的细节
循环列表数据的获取
如果你想发送微信好友消息,那么,我的建议是你先拿到你全部的好友的昵称列表,然后遍历去通讯录列表发送消息。
如果你不先拿所有的好友昵称,你就没办法确定当前执行到哪个好友了,不是吗?
如果不需要拿好友列表,那么请忽略这一块,直接设置list到mQueue里面。
so,我们开始。
首先需要维护一个class,这个class专门是给这个循环发送消息用的辅助类。这个类里面需要存放一个好友昵称Queue,一些标记位,具体之后再谈。
当你点到微信通讯录位置,需要边往下滑,边获取listView中的item来拿当前的昵称列表,然后加到Queue里面,当滑到最底部的时候,需要设置一个标记——获取列表数据结束了。
然后queue.poll();
来一个一个的获取当前需要执行的对象。具体代码如下,里面也有找不到当前昵称,递归滑动寻找的细节处理:
public class SeniorGroupSendMessageMem {
public static LinkedList<String> mQueue = new LinkedList<>();
private static String mCurrent;
private static String mMessage;
private static int mCounter = 0;
private static int mHandleCount = 0;
private static boolean mFlag;//备用flag
private static boolean mSearchOver;
private static String mNeedExcludedLabels;//需要屏蔽的好友标签
private static int mStartIndex;
public static boolean getItemFinishFlag(String item) {
return !mQueue.contains(item);
}
public static String getFirstItem() {
mCurrent = mQueue.poll();
mHandleCount++;
return mCurrent;
}
public static String current() {
return mCurrent;
}
public static void setMessage(String s) {
mMessage = s;
}
public static void add(String name) {
mQueue.add(name);
}
public static int getHandleCount() {
return mHandleCount;
}
public static void add(int index, String name) {
mQueue.add(index, name);
}
public static String message() {
return mMessage;
}
public static String getNeedExcludedLabels() {
return mNeedExcludedLabels;
}
public static boolean isAvalible() {
return mCurrent != null;
}
public static void currentSuccess() {
mCurrent = null;
}
public static void counterAdd() {
mCounter++;
}
public static int getCounter() {
return mCounter;
}
public static void reset(String message) {
if (mQueue == null) {
mQueue = new LinkedList<>();
}
mQueue.clear();
mCounter = 0;
mHandleCount = 0;
mCurrent = null;
mSearchOver = false;
mFlag = false;
mMessage = message;
mNeedExcludedLabels = null;
mStartIndex = 0;
}
public static void reset(String message, String needExcludedLabels) {
reset(message, needExcludedLabels ,0);
}
public static void reset(String message, String needExcludedLabels ,int startIndex) {
reset(message);
mNeedExcludedLabels = needExcludedLabels;
mStartIndex = startIndex;
}
public static boolean isQueueEmpty() {
return mQueue.isEmpty();
}
public static boolean existElement(String name) {
return mQueue.contains(name);
}
public static void searchOver() {
mSearchOver = true;
if (mStartIndex > 0) {
//设置了起点位置
if (mQueue.size() > mStartIndex) {
// 索引正常
for (int i = 0; i < mStartIndex; i++) {
mQueue.poll();
mHandleCount++;
}
} else {
//索引越界 清空
mQueue.clear();
}
}
}
public static boolean hasSearchOver() {
return mSearchOver;
}
public static boolean flag() {
return mFlag;
}
public static void setFlag(boolean flag) {
mFlag = flag;
}
public static void clickFriend2SendMessage() {
if (SeniorGroupSendMessageMem.isQueueEmpty() && SeniorGroupSendMessageMem.hasSearchOver() && mCurrent == null) {
//当前不在执行
//结束任务
TaskId.stop(TaskId.TASK_SENIOR_MASS_SEND_FRIENDS);
return;
}
if (SeniorGroupSendMessageMem.hasSearchOver()) {
AccessibilityNodeInfo nodeInfosById = AccessibilityHelper.findNodeInfosById(WechatUI.ID_ADDRESS_BOOK_LIST_VIEW);
if (nodeInfosById != null) {
String current = SeniorGroupSendMessageMem.getFirstItem();
for (int i = 0; i < nodeInfosById.getChildCount(); i++) {
AccessibilityNodeInfo child = nodeInfosById.getChild(i);
AccessibilityNodeInfo nodeInfosById1 = AccessibilityHelper.findNodeInfosById(child, WechatUI.ID_FROM_BOOK_FRIENG);
if (nodeInfosById1 != null) {
if (current.equals(nodeInfosById1.getText().toString())) {
AccessibilityHelper.performClick(nodeInfosById1);
return;
}
}
}
if (AccessibilityHelper.perform_scroll_forward(nodeInfosById)) {
//如果能滑动 ,添加进去 继续尝试寻找 如果滑动到底了 ,还没找到 放弃, 重新滑倒最上面执行下一个人的寻找
add(0, current);
mHandleCount--;
} else {
scroll2Top(nodeInfosById);
}
clickFriend2SendMessage();
}
}
}
/**
* 滑倒最顶部
*
* @param nodeListView
*/
public static void scroll2Top(AccessibilityNodeInfo nodeListView) {
if (AccessibilityHelper.perform_scroll_backward(nodeListView)) {
UiKit.sleep(200);
scroll2Top(nodeListView);
}
}
}
别说远了,我们是来聊具体循环执行的细节的。不过在上面的代码里面已经体现了细节。
首先每当执行一个item的时候,我先mCurrent = mQueue.poll()
,每到一个页面,基本都要判断当前需不需要执行,也就是mCurrent!=null是不是true,如果不是,就立马返回页面。而当前的功能执行完了,我设置mCurrent = null;
来表示当前没有对象可执行,如果没有,那么你可以自己作出逻辑,返回页面,还是做其他的操作。
总结一下,基本方法就是设置标记位来判断当前需要继续执行,还是返回。然后其中还需要递归滑动来保证当前queue中的昵称找不到的问题。