【发布时间】:2020-01-25 18:57:51
【问题描述】:
我正在使用一个 DialogFragment 来显示一个“模态”底部菜单(更多信息在这里:https://material.io/develop/android/components/bottom-sheet-dialog-fragment/)。由于它包含一种用于 RecyclerView 中包含的项目的上下文菜单,因此它可能会在运行时显示多次。
但是,总是调用DialogFragment.show(),同时调用Fragment.onCreateView(),这会导致布局膨胀,这可以(?)被认为是要在UI线程中计算的“繁重”任务,我想出于性能原因避免。因此,为了避免每次显示 DialogFragment 时布局膨胀,我创建了一个 ViewGroup 成员对象,指向要返回的视图 Fragment.onCreateView() 以便重用,如下所示:
public class BottomMenu extends BottomSheetDialogFragment {
private ViewGroup mLayout;
private TextView mLabel;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mLayout == null) {
mLayout = (ViewGroup) LayoutInflater.from(getContext()).inflate(R.layout.bottom_sheet, container, false);
mLabel = mLayout.findViewById(R.id.bottom_sheet_label);
}
return mLayout;
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
// The view cannot be reused if it's already attached to the previous parent view
((ViewGroup) mLayout.getParent()).removeView(mLayout);
}
public void setLabel(String label) {
mLabel.setText(label)
}
}
但是一旦第一次使用,这样的视图必须从 Fragment 容器视图中分离出来才能重用(参见发布的 sn-p 上的 onDismissed() 覆盖方法),这似乎是一个讨厌的解决方法
所以我发布这个问题是为了检查是否有人知道为同一片段重用布局的更好方法
更多细节在这里:
public class ActivityMain extends AppCompatActivity {
private BottomMenu mBottomMenu;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[...]
mBottomMenu = new BottomMenu();
}
@Override
public boolean onLongClick(View v) {
mBottomSheet.setLabel(label);
// The following calls onCreateView() in Fragment, so try to return
// there the previously inflated layout, if any
mBottomSheet.show(getSupportFragmentManager(), "TAG?");
return true;
}
}
【问题讨论】:
-
“可以(?)被认为是要在 UI 线程中计算的“繁重”任务”——通常不会,尤其是对于像您这样的小型布局。 “出于性能原因,我想避免这种情况”——为什么?您是否有证据表明它导致了问题?
-
好吧,实际上并非如此,但我认为这是一种很好的做法,因为在使用较重的布局@CommonsWare 时性能会更好
-
“我认为这是一种很好的做法”——为什么?如果你无法解释这种额外的复杂性和脆弱性如何使用户受益,为什么它会在代码审查中被接受?通常,框架和库提供视图回收,这种回收几乎肯定会带来好处(
AdapterView、RecyclerView、ViewPager等)。其他一切都需要一些证据证明它值得复杂。 -
只是因为当您可以多次使用时,我不认为多次膨胀布局是有效的,所以如果有一种更有效的简单方法我会使用它(即使它没有引入显着性能改进)。而且我猜库和框架示例在这里不适用,因为它们被设计为被许多开发人员广泛使用,用于多种目的,而这种情况只是特定于应用程序的。我不是在寻找过早的优化,只是为了做一个合适的事情
-
“所以如果有一种更简单的方法可以提高效率,我会使用它”——在这种情况下,我不相信有。虽然有些场景可以重用片段及其视图,但我认为
DialogFragment和子类并不实用。
标签: android performance android-fragments layout-inflater