如何“撤销”ViewStub?

29

我可以在运行时填充一个ViewStub。假设我想让它消失,然后根据发生的某些事件(例如,根据用户在屏幕上选择的内容膨胀和缩小的工具栏)再次填充它。

我可以使用View.setVisibility(View.GONE)....是否还有其他方法?

或者我在这里做错了什么吗?

谢谢!:)


setVisibility(View.GONE) 更加具有描述性。 - st0le
你对View.GONE有什么不喜欢的地方? - Cheryl Simon
我并不讨厌它。只是想知道这是否是正确的方法,或者是否有其他更有效的方法? - Sid
3个回答

37

布局膨胀可能会很昂贵,特别是在旧设备上。将ViewStub视为一种惰性加载机制,用于可能或可能不会扩展的视图子树,而不是在运行时交换视图层次结构中的部分的方法。一旦充气,使用VISIBLE/GONE之间进行交换没有任何问题。GONE会使框架在昂贵的遍历期间跳过该子树。

只要您不需要充气视图使用的内存,这就是正确的。将可见性设置为GONE不会释放任何内存;它仅将视图标记为已隐藏,以供布局和绘制目的。要释放viewstub充气视图的内存,您必须实际删除充气视图,并再次替换为新的viewstub以供将来使用。


你好 @adamp,我有一个疑问。如果我创建一个简单的线性布局,并动态添加一个子视图,当我不需要它时,从线性布局中删除该子视图,这样会完全删除子视图。当你想要内存优化时,这是一个好方法吗?因为一旦视图存根被填充,我们就不能通过将其设置为GONE来删除该视图。 - KDeogharkar

0

是的,你可以随时删除。我刚刚做过了。

ViewStub stub = findById(...);
View v = stub.inflate();

并在任何事件上设置视图可见性。

v.setVisibility(View.GONE);

2
将可见性设置为GONE并不会将其删除,它只是隐藏了它。 - Pkmmte

0
这是一段代码,用于解压缩视图存根。
private Boolean isErrorViewInflated = false;
private ViewStub errorViewStub;  
/* here a method that gets a view.  If the view is already inflated,
 * it uses that view, else it inflates the view. It also creates a viewStub
 * object which will be used to replace the inflated view when it needs to 
 * be deflated.
 /
public RelativeLayout getErrorView() {
    RelativeLayout errorView = null;
    if (isErrorViewInflated) {
        errorView = activity.findViewById(R.id.error_view);
    } else {
        ViewStub stub = activity.findViewById(R.id.error_view_stub);
        errorView = (RelativeLayout) stub.inflate();
        errorViewStub = new ViewStub(getContext(), stub.getLayoutResource());
        isErrorViewInflated = true;
    }
    return errorView;
}

/* Here's the code that deflates an inflated ErrorView back to a ViewStub
 */
private void deflateErrorView() {
    if (isErrorViewInflated) {
        RelativeLayout errorView = activity.findViewById(R.id.error_view);
        ViewGroup parent = (ViewGroup)errorView.getParent();
        int index = parent.indexOfChild(errorView);
        parent.removeView(errorView);
        parent.addView(errorViewStub, index);
        isErrorViewInflated = false;
    }
}

如果你想知道的话,你不能只缓存原始的ViewStub并用它来替换充气的视图。这是因为原始的ViewStub对象有一个父视图,如果你尝试将该视图添加到任何视图组中(即使它是原来所包含的视图组),你会得到一个错误。因此,解决这个问题的方法是使用与原始ViewStub中相同的布局资源创建一个新的ViewStub对象。
如果你不关心充气的ViewStub占用的空间,当不再需要该充气的ViewStub时,"View.GONE"的解决方案是可以的。对于将可见性设置为GONE的视图,没有显著的运行时开销。在我的情况下,我一直在使用ViewStub来显示错误、日志和控制台显示区域,当它们不使用时,我希望系统能够垃圾回收与这些视图相关联的对象。

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