探索 Android 中的视图树

Exploring the view tree in Android

它可能有点抽象,但我想知道你们中的一些人是否有解决该问题的合适方法:

我的布局很复杂,我需要找到某种视图类型的所有实例。

我的解决方案很少,但我发现其中 none 个是完美的,我想知道是否有其他方法或方法可以改进它们。

我的第一个选择

我们可以使用 getChildCount()getChildAt() 在视图树中进行迭代,然后像许多 SO 答案一样使用 instanceof 检查。

for (int i = 0; i<parentContainer.getChildCount(); i++){
    View child = getChildAt(i);
    if (child instanceof BlaBla){
        // Do something wonderful
    }
}

这是非常低效的,因为我在很多地方都有这些实例,特别是在嵌套的地方,所以我需要使这个方法递归。

我的第二个选择

将使用动态标签或 ID 并使用 findViewByIdfindViewWithTag。但问题是它需要配置更多东西,并且一如既往地使软件更加复杂。

So my question is: how can I do a complete search in the view tree in order to find all instances of a component without doing the search myself (because it would be probably be very inefficient)? Is that somehow possible?

因此,我不确定第二个选项是否可行,因为在这种情况下,您需要在运行时创建此视图并分配一些生成的 ID 和一些位掩码以便稍后识别它们。如果要从布局创建视图,您最终会遍历树视图并分配这些特殊 ID,这几乎符合第一个选项。

在我的项目中,我还必须动态地将颜色应用到某些视图,并且我在没有递归的情况下进行。模式如下:

ArrayList<View> views = new ArrayList<>();
views.add(getWindow().getDecorView());

    do {
      View v = views.remove(0);
       if (v instanceof ViewGroup) {
           ViewGroup group = (ViewGroup) v;
           for (int i = 0; i < group.getChildCount(); i++) {
             views.add(group.getChildAt(i));
           }
       }
       if (v instanceof MyCustomView) {
         //do whatever you need here
       }
    } while(!views.isEmpty());

所以你摆脱了使用递归并用自己的堆栈和迭代替换它。这个解决方案非常有效,特别是如果你可以跳过像 ListView、RecyclerView 这样的东西。