我有一个带有 3 个选项卡的 BottomNavigationView。在每次选项卡单击时,它都会调用 .replace()
private void initBottomNavigation() {
mBottomNavigation.setOnNavigationItemSelectedListener(menuItem -> {
switch (menuItem.getItemId()) {
case R.id.bottomnav_admin_home: <---- Tab 1
getSupportFragmentManager().beginTransaction()
.replace(
R.id.admin_fragment_container,
new AdminHomeFragment(),
Constants.FRAGMENT_ADMIN_HOME
)
.commit();
}
...Tab two
....Tab three
return true;
```
在我的第三个选项卡中,我有一个在 fragment 容器顶部添加 fragment 的按钮:当我单击该按钮时,它会调用它以在 fragment 容器的顶部添加另一个 fragment :
getParentFragmentManager().beginTransaction()
.add(
R.id.admin_fragment_container,
new DeactivateUserFragment(),
Constants.FRAGMENT_ADMIN_DEACTIVATE_USER
)
.addToBackStack(null)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
当我在 已添加 fragment ,我点击调用 .replace()
的第二个选项卡,它会导致我的 内存泄漏已添加 分段。我已经减少了添加的 Fragment 中的所有代码,但我不知道为什么它仍然在泄漏。
添加 fragment 的完整代码:
public class DeactivateUserFragment extends Fragment{
private static final String TAG = "FragmentDeactivatedUser";
@BindView(R.id.recycler_view) RecyclerView mRecycler;
@BindView(R.id.parent_layout) ViewGroup mParentLayout;
@BindView(R.id.progress_bar) ProgressBar mProgressBar;
private Context mContext;
private SimpleListUsersAdapter mAdapter;
private ArrayList<UserInfo> mList = new ArrayList<>();
private DeactivateViewModel mViewModel;
private AuthStateManager mAuthStateManager;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getContext();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_admin_deactivate_user, container, false);
ButterKnife.bind(this, view);
return view;
}
@OnClick(R.id.btn_back)
public void onBackBtnClick(){
getParentFragmentManager().popBackStack();
}
}
泄漏:androidx.coordinatorlayout.widget.CoordinatorLayout instance
Leaking: YES (ObjectWatcher was watching this because com.example.
testproject.ui.admin.deactivate.DeactivateUserFragment received
Fragment#onDestroyView() callback (references to its views should be
cleared to prevent leaks))
Retaining 106.7 kB in 1469 objects
key = e50280e9-58bd-4ecd-bc1b-a2d6cc188639
watchDurationMillis = 108539
retainedDurationMillis = 103532
View not part of a window view hierarchy
View.mAttachInfo is null (view detached)
View.mID = R.id.parent_layout
View.mWindowAttachCount = 1
mContext instance of com.example.testproject.ui.admin.AdminActivity
with mDestroyed = false
编辑 1:________________________________ 为什么删除这三行不再导致内存泄漏?
@BindView(R.id.recycler_view) RecyclerView mRecycler;
@BindView(R.id.parent_layout) ViewGroup mParentLayout;
@BindView(R.id.progress_bar) ProgressBar mProgressBar;
我没有在任何代码中使用变量,只是将它们绑定(bind)。我非常困惑这是如何导致泄漏的
编辑 2:__________________________________
我尝试在
onDestroyView()
中将 View 设置为 null和解开Butterknife,但仍然泄漏。https://github.com/JakeWharton/butterknife/issues/585
@Override
public void onDestroyView() {
Log.d(TAG, "onDestroyView: Called");
unbinder.unbind();
mRecycler = null;
mParentLayout = null;
mProgressBar = null;
super.onDestroyView();
}
我试过一一删除 View ...进度条、回收器和 mParentLayout。只有在我删除所有 3 个之前,它才不再泄漏我从 fragment 中删除了 Butterknife 并且只使用 findViewById 但仍然有同样的问题
最佳答案
修复是为黄油刀的 Binder
设置一个全局变量。在我的 fragment 中并调用 Unbind
在 onDestroyView()
private Unbinder unbinder;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_admin_link_family, container, false);
return view;
}
我也绑定(bind)了我的适配器private SimpleListUsersAdapter adapter;
Inside Adapter class
class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.action_type)
TextView userAction;
@BindView(R.id.date)
TextView date;
@BindView(R.id.amount)
TextView amount;
ViewHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
所以我还需要在 onDestroyView
中将适配器设置为 nullFragment Class
@Override
public void onDestroyView() {
super.onDestroyView();
adapter = null;
unbinder.unbind();
}
需要同时做以阻止泄漏
关于android - 添加 fragment 并调用 .replace() 导致添加的 fragment 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66403565/