RecyclerView 不会在方向更改时从适配器中注销自身



我曾经在我的Android应用程序中使用ListView,最近我切换到RecyclerView,并观察到它在方向上引入了一些内存泄漏。在进一步调查中,原因显而易见

设置

一个托管fragment的单个activity,其实例在配置更改中保留。fragment在其布局文件中包含一个RecyclerView,该文件使用自定义adapter

填充

向下钻

每当为这2个视图中的任何一个设置Adapter时,它们都会向适配器注册,以监视数据更改并更新UI。ListView

上的配置上解开自身
@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    ...
    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
        mDataSetObserver = null;
    }
    ...
}

不幸的是,RecyclerView不这样做

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    if (mItemAnimator != null) {
        mItemAnimator.endAnimations();
    }
    mFirstLayoutComplete = false;
    stopScroll();
    mIsAttached = false;
    if (mLayout != null) {
        mLayout.onDetachedFromWindow(this, mRecycler);
    }
    removeCallbacks(mItemAnimatorRunner);
}

证明

我更改了方向很多次,然后进行了堆转储,然后使用Eclipse的垫子阅读。我确实看到我的活动有很多实例,因为RecyclerView实例没有unregister,并且他们对我的活动有很大的参考!

我想念什么吗?你们如何确保RecyclerView不会泄漏您的活动?

fragment

public class ExampleFragment extends Fragment {
    private ExampleAdapter mAdapter = null;
    public static ExampleFragment newInstance() {
        return new ExampleFragment();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        setupAdapterIfRequired();
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_example, container, false);
    }
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setupRecyclerView(getView());
    }
    private void setupAdapterIfRequired() {
        if (mAdapter == null) {
            mAdapter = new ExampleAdapter();
        }
    }
    private void setupRecyclerView(View rootView) {
        RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.list);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
        recyclerView.setAdapter(mAdapter);
    }
}

将其添加到Fragment为我停止泄漏:

@Override
public void onDestroyView() {
    super.onDestroyView();
    recyclerView.setAdapter(null);
}

RecyClerview的问题不是。它是因为您正在设置setRetainInstance(true)

setRetainInstance()仅应与片段一起使用,而无需查看或会导致内存泄漏。

当定向变化活动将被杀死时,但是在碎片中查看仍然使用该活动中的上下文。这就是为什么您会看到内存泄漏。

我遇到了同一问题。我进行了一些搜索,但没有找到有关此线程的任何内容。

所以我自己询问:为什么我需要RecyClerview.Adapter中的上下文?(在阵列ADAPTER中,您将其用于Infalte一些布局)但是,在这种新模式中,您可以使用父上下文来夸大布局:

,例如

public class RecyclerViewAdapter extends RecyclerView.Adapter<VH> {
     @Override
     public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          return LayoutInflater.from(parent.getContext()).inflate(R.layout.item_action, parent, false);
     }
}

相同以绑定它

@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
    String myString = holder.itemView.getContext().getString(R.string.app);
    ((Button)holder.itemView).setText(myString);
}

希望它能帮助

相关内容

最新更新