Android - 递归删除布局中的视图

6
有没有一种方法可以递归地从布局中删除视图?函数 removeAllViewsInLayout() 似乎无法完成此任务(它会从布局中删除所有视图,但不会删除布局的子视图)。在我的程序中,我动态添加了一些FrameLayouts到RelativeLayout上,并在这些FrameLayouts上添加了一些ImageViews和TextViews。所以我想知道是否需要编写自己的递归删除视图代码,还是有一些可用的方法。

你尝试过直接移除FrameLayout而不是TextViews/ImageViews,然后回滚到FrameLayout吗? - Rob
如果我按照你说的方法逐个查看视图,它是有效的(这也是我正在做的)。所以我只想知道是否有一个函数可以为我完成这项工作,或者我必须自己完成它。 - Alesqui
3个回答

4
我认为你可以将布局视为一棵树。因此,你只需要引用根节点的参考。如果你删除它,它将与其子项一起被收集,因为没有其他引用它们。
如果由于某些原因在此操作后仍然看到一些视图,则意味着它们属于另一个节点。你总是可以使用Hierarchy Viewer来更好地“查看”你的UI:http://developer.android.com/guide/developing/debugging/debugging-ui.html

我以为那样会起作用,但我不确定是要删除根节点还是遍历每个视图并将它们删除。也许有一些诀窍可以采用其中一种方式。但既然似乎没有,你的答案就是正确的 :D - Alesqui

1

这不是一个递归示例,但我相信它可以解决你的问题:

public void ClearRelLayout(RelativeLayout RL){
    for(int x=0;x<RL.getChildCount();x++){
        if(RL.getChildAt(x) instanceof FrameLayout){
            FrameLayout FL = (FrameLayout) RL.getChildAt(x);
            FL.removeAllViewsInLayout();
        }
    }
    RL.removeAllViewsInLayout();
}

不使用递归,只需循环遍历每个子元素,并在其为FrameLayout时将其清除。

应该调用removeAllViews()而不是removeAllViewsInLayout()。后者的JavaDoc中写道:“除非你正在扩展ViewGroup并且了解视图测量和布局流程,否则不要调用此方法。” - osundblad
1
我认为你可以做得更好,而不是检查 instanceof FrameLayout,你可以检查 instanceof ViewGroup。这样你就可以捕获其他布局(LinearLayoutGridLayout等)。 - Ehtesh Choudhury

1

首先,通常应该调用 removeAllViews()而不是 removeAllViewsInLayout(),请阅读JavaDoc以了解它们之间的区别。

另外,这些函数都不是递归的,它们只会从调用它们的对象中删除视图。子结构不会改变。如果子结构引用了其他被保留的对象,则可能会导致问题甚至内存泄漏。

例如,如果您拥有以下结构:

    <LinearLayout id='top'>
      <LinearLayout id='sub'>
        <Button id='b'/>
      </LinearLayout>
    </LinearLayout>

如果在布局top上调用removeAllViews(),那么布局sub仍将引用b(并且b将引用sub作为其父级)。这意味着您不能在没有先删除其父级(sub)的情况下在其他地方重用b。如果这样做,您将会得到一个异常。


但是,布局sub及其所有子元素是否会被垃圾回收呢?我一直在尝试找到答案,希望是肯定的,因为没有其他东西会引用sub - Tony Chan
它应该可以,因为它们没有外部引用,但我不确定(一个糟糕编写的垃圾回收可能会留下它们,或者安卓中可能有其他隐藏的引用)。 - osundblad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接