底部 sheet 片段内存泄漏
Bottom sheet fragment memory leak
我正在使用 leakcanary,它说你的底部 sheet 片段正在泄漏。但是我看不出问题出在哪里。
我该如何修复泄漏?
public class TokensExplainedFragment extends BottomSheetDialogFragment implements HasSupportFragmentInjector {
private static final String TAG = "TokensExplainedFragment";
private View mainView;
@Inject
DispatchingAndroidInjector<Fragment> childFragmentInjector;
@Inject
SessionManager sessionManager;
@Inject
ViewModelProviderFactory providerFactory;
public TokensExplainedFragment() {
}
@Override
public void onAttach(Context context) {
AndroidSupportInjection.inject(this);
super.onAttach(context);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.fragment_tokens_explained, container, false);
return mainView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
return dialog;
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return childFragmentInjector;
}
}
我是这样开始的:
TokensExplainedFragment bottomSheetFragment = new TokensExplainedFragment();
bottomSheetFragment.show(getActivity().getSupportFragmentManager(), bottomSheetFragment.getTag());
泄漏痕迹:
getSupportFragmentManager
和 getFragmentManager
都是顶级 Activity 的片段管理器。要在片段级别内管理片段,请使用 getChildFragmentManager
bottomSheetFragment.show(getChildFragmentManager(), bottomSheetFragment.getTag());
根据 Android sources,ConnectivityThread 是:
Shared singleton connectivity thread for the system. This is a thread for
connectivity operations such as AsyncChannel connections to system services.
Various connectivity manager objects can use this singleton as a common
resource for their handlers instead of creating separate threads of their own.
在这里我们可以看到这个线程是 运行,一条消息 post 发送给它并且当前在该线程上执行的消息引用了 TokensExplainedFragment。
我怀疑 TokensExplainedFragment 所做的比 Whosebug 中共享的要多(例如一些使用 sessionManager 的代码),并且在该额外代码中可能有调用连接系统服务的东西(例如 wifi、互联网、蓝牙等)。这可能会触发延迟 post 的消息到连接线程,并且 post 应该被取消但没有。
我正在使用 leakcanary,它说你的底部 sheet 片段正在泄漏。但是我看不出问题出在哪里。
我该如何修复泄漏?
public class TokensExplainedFragment extends BottomSheetDialogFragment implements HasSupportFragmentInjector {
private static final String TAG = "TokensExplainedFragment";
private View mainView;
@Inject
DispatchingAndroidInjector<Fragment> childFragmentInjector;
@Inject
SessionManager sessionManager;
@Inject
ViewModelProviderFactory providerFactory;
public TokensExplainedFragment() {
}
@Override
public void onAttach(Context context) {
AndroidSupportInjection.inject(this);
super.onAttach(context);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.fragment_tokens_explained, container, false);
return mainView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
return dialog;
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return childFragmentInjector;
}
}
我是这样开始的:
TokensExplainedFragment bottomSheetFragment = new TokensExplainedFragment();
bottomSheetFragment.show(getActivity().getSupportFragmentManager(), bottomSheetFragment.getTag());
泄漏痕迹:
getSupportFragmentManager
和 getFragmentManager
都是顶级 Activity 的片段管理器。要在片段级别内管理片段,请使用 getChildFragmentManager
bottomSheetFragment.show(getChildFragmentManager(), bottomSheetFragment.getTag());
根据 Android sources,ConnectivityThread 是:
Shared singleton connectivity thread for the system. This is a thread for connectivity operations such as AsyncChannel connections to system services. Various connectivity manager objects can use this singleton as a common resource for their handlers instead of creating separate threads of their own.
在这里我们可以看到这个线程是 运行,一条消息 post 发送给它并且当前在该线程上执行的消息引用了 TokensExplainedFragment。
我怀疑 TokensExplainedFragment 所做的比 Whosebug 中共享的要多(例如一些使用 sessionManager 的代码),并且在该额外代码中可能有调用连接系统服务的东西(例如 wifi、互联网、蓝牙等)。这可能会触发延迟 post 的消息到连接线程,并且 post 应该被取消但没有。