所以我可以在运行时膨胀 ViewStub。假设我想让它消失,然后可能会根据发生的某些事件再次膨胀(例如,根据用户在屏幕上选择的内容膨胀和收缩的工具栏)。
我可以使用 View.setVisibility(View.GONE)....还有其他方法吗?
或者我在这里做错了什么?
谢谢! :)
膨胀布局可能会很昂贵,尤其是在旧设备上。将 ViewStub 更多地视为视图子树的延迟加载机制,它可能会也可能不会扩展,而不是在运行时交换视图层次结构部分的方法。一旦膨胀,在 VISIBLE/GONE 之间交换就没有问题了。 GONE 将使框架在昂贵的遍历过程中跳过该子树。
只要您不需要膨胀视图使用的内存,这就是正确的。将可见性设置为 GONE 不会释放任何内存;它仅将视图标记为已消失,以用于布局和绘图目的。要释放视图存根的膨胀视图的内存,您实际上必须删除膨胀视图并用新的视图存根再次替换它以供将来使用。
是的,您可以随时删除。我刚刚已经完成了。
ViewStub stub = findById(...);
View v = stub.inflate();
并设置任何事件的视图可见性。
v.setVisibility(View.GONE);
这里有一些缩小视图存根的代码:
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 对象有一个父 View,如果您尝试将该视图添加到任何视图组中(即使它与最初包含的视图组相同),您会收到错误消息。因此,解决此问题的方法是使用与原始 ViewStub 中相同的布局资源创建一个新的 ViewStub 对象。
如果不再需要膨胀的 ViewStub 时您不关心膨胀的 ViewStub 占用的空间,那么“View.GONE”解决方案就可以了。对于可见性设置为 GONE 的视图,没有显着的运行时开销。就我而言,我一直在使用 ViewStub 来处理错误、日志和控制台显示区域,并且我希望系统能够在不使用这些视图时对与这些视图关联的对象进行垃圾收集。