Android RecyclerView适配器don';我不想重复使用视图持有者
我面临着内存泄漏的问题。 我有一个带有Android RecyclerView适配器don';我不想重复使用视图持有者,android,android-fragments,android-recyclerview,Android,Android Fragments,Android Recyclerview,我面临着内存泄漏的问题。 我有一个带有FragmentStatePagerAdapter的片段,里面有一个片段(还有更多,我留下一个只是为了测试)。 此片段包含具有几个不同视图持有者的RecyclerView 例如,这是一个简单的ViewHolder,仅在RecyclerView中的一个位置用作标题 public class CurrencyViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.currency_date
FragmentStatePagerAdapter
的片段,里面有一个片段(还有更多,我留下一个只是为了测试)。
此片段包含具有几个不同视图持有者的RecyclerView
例如,这是一个简单的ViewHolder
,仅在RecyclerView
中的一个位置用作标题
public class CurrencyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.currency_date)
TextView currencyDate;
@BindView(R.id.currency_usd)
TextView currencyUsd;
@BindView(R.id.currency_eur)
TextView currencyEur;
@BindView(R.id.currency_info)
LinearLayout currencyInfo;
public CurrencyViewHolder(View itemView, boolean nightMode) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bind(CbrResponse response) {
currencyDate.setText(String.format("asdsdf %s", response.getDate()));
currencyUsd.setText(String.format("USD %,.2f", response.getUSD().getValue()));
currencyEur.setText(String.format("EUR %,.2f", response.getEUR().getValue()));
}
}
但是,正如你所看到的,在这张照片上
我有12个这个类的实例。我已经对这个片段中的另一个片段进行了12次交易,出于某种原因,我的视图持有者被重新创建强>
我认为这是导致我内存泄漏的原因。我不确定你想要哪段代码,所以我放了一些适配器方法,以防你想看到它
NewsListRecyclerAdapter
是我的适配器,下面的代码在这里执行。请注意,此类的intance只创建一次
UPD
这是我的带有ViewPager的framgnet:
public class PagerListsFragment extends NightModeFragment {
private final String LOG_TAG = PagerListsFragment.class.getSimpleName();
@BindView(R.id.circlePagerListsIndicator)
TextCirclePageIndicator pageIndicator;
@BindView(R.id.settings_button)
ImageButton settingsButton;
@BindView(R.id.pager_lists_header)
FrameLayout pagerListsHeader;
@BindView(R.id.pagerLists)
ViewPager viewPager;
@BindView(R.id.linear_layout)
LinearLayout linearLayout;
// ArticlesFragment articlesFragment;
// FavouritesFragment favouritesFragment;
PagerListsFragmentAdapter fragmentAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("PagerListsFragment", "onCreate");
fragmentAdapter = new PagerListsFragmentAdapter(getContext(), getChildFragmentManager());
// articlesFragment = new ArticlesFragment();
// favouritesFragment = new FavouritesFragment();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.d("PagerListsFragment", "onViewCreated");
viewPager = (ViewPager) view.findViewById(R.id.pagerLists);
viewPager.setAdapter(fragmentAdapter);
viewPager.setPageMargin((int) getResources().getDimension(R.dimen.lists_pager_margin));
pageIndicator =
(TextCirclePageIndicator) view.findViewById(R.id.circlePagerListsIndicator);
pageIndicator.setViewPager(viewPager);
pagerListsHeader = (FrameLayout) view.findViewById(R.id.pager_lists_header);
linearLayout = (LinearLayout) view.findViewById(R.id.linear_layout);
final int topMarginUp = 0;
final int topMarginDown = getResources().getDimensionPixelSize(R.dimen.toolbar_height);
setTopMargin(linearLayout, topMarginDown);
ImageButton settingsButton = (ImageButton) view.findViewById(R.id.settings_button);
settingsButton.setOnClickListener(v -> ((MainActivity) getActivity()).openSettings());
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("PagerListsFragment", "onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("PagerListsFragment", "onDestroy");
}
@Override
protected int getLayoutResource() {
return R.layout.fragment_list_paged;
}
private void setTopMargin(View view, int topMarginInPx) {
ViewGroup.MarginLayoutParams layoutParams =
(ViewGroup.MarginLayoutParams) view.getLayoutParams();
layoutParams.topMargin = topMarginInPx;
view.requestLayout();
}
public static PagerListsFragment getInstace(Bundle extra) {
PagerListsFragment fragment = new PagerListsFragment();
fragment.setArguments(extra);
return fragment;
}
}
这是我的片段,其中RecyclerView是:
public class NewsFragment extends BaseNewsFragment implements NewsViewState,
TeaserViewHolder.OnItemClickListener {
private final Category category = new Category(Category.NEWS);
@InjectPresenter
NewsPresenter presenter;
protected NewsListRecyclerAdapter adapter;
protected EndlessRecyclerOnScrollListener scrollListener;
@BindView(R.id.news_recycler)
protected RecyclerView newsRecycler;
@BindView(R.id.refresh)
protected SwipeRefreshLayout refresh;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("NewsFragment", "onCreate");
adapter = new NewsListRecyclerAdapter(getActivity(), this);
presenter.loadNewsAndCurrency(0, true, category);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
scrollListener = new EndlessRecyclerOnScrollListener(manager) {
@Override
public void onLoadMore(int current_page) {
presenter.loadNewsAndCurrency(adapter.getItemCount(), false, category);
}
};
newsRecycler.addOnScrollListener(scrollListener);
newsRecycler.setItemAnimator(null);
newsRecycler.setLayoutManager(manager);
newsRecycler.setAdapter(adapter);
refresh.setOnRefreshListener(() -> {
scrollListener.reset(0, true);
presenter.loadNewsAndCurrency(0, true, category);
if (!DEBUG) {
FlurryAgent.logEvent(FlurryHelper.USER_NEWS_LIST);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("NewsFragment", "onDestroy");
if (newsRecycler != null) {
newsRecycler.setAdapter(null);
}
}
@Override
public void onTeasersLoaded(List<NewsListItem> teasers, boolean refresh) {
adapter.addAll(teasers, refresh);
}
@Override
public void removeTeaser(NewsListItem item) {
Log.d("BaseNewsFragment", "Removing item.getType():" + item.getType());
if (item.getTeaser().getCategoryId() == category.getCategoryInt()) {
adapter.remove(item);
}
}
@Override
public void addTeaser(NewsListItem item) {
if (item.getTeaser().getCategoryId() == category.getCategoryInt()) {
adapter.add(item);
}
}
@Override
public void onCurrencyLoaded(NewsListItem currencyItem) {
adapter.add(currencyItem);
}
@Override
public void onItemClick(NewsListItem teaser) {
((MainActivity) getActivity()).onNewsSelected(teaser.getTeaser().getUuid(), category.getCategoryInt());
adapter.add(teaser);
}
@Override
public void setNightMode() {
adapter.setNightMode(isNightMode);
newsRecycler.setBackgroundColor(getCurrentBackgroundColor());
}
@Override
public void hideProgress() {
refresh.setRefreshing(false);
}
@Override
public void showProgress() {
refresh.setRefreshing(true);
}
}
公共类NewsFragment扩展BaseNewsFragment实现NewsViewState,
triserviewholder.OnItemClickListener{
私有最终类别=新类别(Category.NEWS);
@注射者
新闻主持人;
受保护的NewsListRecyclerAdapter适配器;
受保护的EndlesRecycleronScrollListener scrollListener;
@BindView(R.id.news\u回收商)
受保护的回收站查看新闻回收站;
@BindView(R.id.refresh)
受保护的布局刷新;
@凌驾
创建时的公共void(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d(“新闻片段”、“onCreate”);
adapter=新的NewsListRecyclerAdapter(getActivity(),this);
presenter.LoadNews和Currency(0,true,类别);
}
@凌驾
已创建视图上的公共void(视图,捆绑保存状态){
super.onViewCreated(视图,savedInstanceState);
LinearLayoutManager=newlinearlayoutmanager(getActivity());
scrollListener=新的EndlesRecycleronScrollListener(管理器){
@凌驾
public void onLoadMore(int当前页面){
loadNewsAndCurrency(adapter.getItemCount(),false,category);
}
};
addOnScrollListener(scrollListener);
newsRecycler.setItemAnimator(空);
newsRecycler.setLayoutManager(管理器);
newsRecycler.setAdapter(适配器);
refresh.setOnRefreshListener(()->{
scrollListener.reset(0,true);
presenter.LoadNews和Currency(0,true,类别);
如果(!调试){
FlurryAgent.logEvent(FlurryHelper.USER\u新闻列表);
}
});
}
@凌驾
公共无效onDestroyView(){
super.onDestroyView();
Log.d(“新闻片段”、“onDestroy”);
if(新闻回收器!=null){
newsRecycler.setAdapter(null);
}
}
@凌驾
public void ontasersloaded(列表摘要、布尔刷新){
adapter.addAll(摘要、刷新);
}
@凌驾
公共无效删除器(NewsListItem){
Log.d(“BaseNewsFragment”,“删除item.getType():”+item.getType());
if(item.getTeaser().getCategoryId()==category.getCategoryInt()){
适配器。移除(项目);
}
}
@凌驾
public void addstriser(NewsListItem){
if(item.getTeaser().getCategoryId()==category.getCategoryInt()){
添加(项目);
}
}
@凌驾
加载currencyItem时的公共无效(NewsListItem currencyItem){
adapter.add(currencyItem);
}
@凌驾
公共链接(NewsListItem摘要){
((MainActivity)getActivity()).onNewsSelected(trister.getTeaser().getUuid(),category.getCategoryInt());
适配器。添加(摘要);
}
@凌驾
公共void setNightMode(){
adapter.setNightMode(isNightMode);
setBackgroundColor(getCurrentBackgroundColor());
}
@凌驾
public void hideProgress(){
refresh.setRefreshing(false);
}
@凌驾
公共服务进展{
refresh.setRefreshing(true);
}
}
我无法滑动片段,因为我在ViewPager中只剩下一个片段(只是为了测试。)您的片段被重新创建了多少次?12ViewHolder
计数可能来自使用FragmentStatePagerAdapter
刷卡时重新创建的新Fragment
,从而重新创建RecyclerView
、RecyclerAdapter
和ViewHolder
在查看堆之前,您是否尝试过使用启动GC
?它们可能是GC
等待收集已销毁的旧视图,但由于有足够的可用内存,GC
将不会收集这些视图。您的片段被重新创建了多少次?12ViewHolder
计数可能来自使用FragmentStatePagerAdapter
刷卡时重新创建的新Fragment
,从而重新创建RecyclerView
、RecyclerAdapter
和ViewHolder
在查看堆之前,您是否尝试过使用启动GC
?它们可能是GC
等待收集已销毁的旧视图,但由于有足够的可用内存,GC
将不会收集这些内容。您真正的意思是“我已将12个事务从这一个片段收集到另一个片段”?您使用过ViewPager吗?@Ewoks我的意思是我在这个recyclerView片段和其他片段之间导航了12次。@Hareshchelana是的,我使用ViewPager与recyclerView一起存储片段。FragmentStatePagerAdapter是他的改编者我不确定我是否看到了这个问题。。您的RecyclerView有12个visi
public class NewsFragment extends BaseNewsFragment implements NewsViewState,
TeaserViewHolder.OnItemClickListener {
private final Category category = new Category(Category.NEWS);
@InjectPresenter
NewsPresenter presenter;
protected NewsListRecyclerAdapter adapter;
protected EndlessRecyclerOnScrollListener scrollListener;
@BindView(R.id.news_recycler)
protected RecyclerView newsRecycler;
@BindView(R.id.refresh)
protected SwipeRefreshLayout refresh;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("NewsFragment", "onCreate");
adapter = new NewsListRecyclerAdapter(getActivity(), this);
presenter.loadNewsAndCurrency(0, true, category);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
scrollListener = new EndlessRecyclerOnScrollListener(manager) {
@Override
public void onLoadMore(int current_page) {
presenter.loadNewsAndCurrency(adapter.getItemCount(), false, category);
}
};
newsRecycler.addOnScrollListener(scrollListener);
newsRecycler.setItemAnimator(null);
newsRecycler.setLayoutManager(manager);
newsRecycler.setAdapter(adapter);
refresh.setOnRefreshListener(() -> {
scrollListener.reset(0, true);
presenter.loadNewsAndCurrency(0, true, category);
if (!DEBUG) {
FlurryAgent.logEvent(FlurryHelper.USER_NEWS_LIST);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.d("NewsFragment", "onDestroy");
if (newsRecycler != null) {
newsRecycler.setAdapter(null);
}
}
@Override
public void onTeasersLoaded(List<NewsListItem> teasers, boolean refresh) {
adapter.addAll(teasers, refresh);
}
@Override
public void removeTeaser(NewsListItem item) {
Log.d("BaseNewsFragment", "Removing item.getType():" + item.getType());
if (item.getTeaser().getCategoryId() == category.getCategoryInt()) {
adapter.remove(item);
}
}
@Override
public void addTeaser(NewsListItem item) {
if (item.getTeaser().getCategoryId() == category.getCategoryInt()) {
adapter.add(item);
}
}
@Override
public void onCurrencyLoaded(NewsListItem currencyItem) {
adapter.add(currencyItem);
}
@Override
public void onItemClick(NewsListItem teaser) {
((MainActivity) getActivity()).onNewsSelected(teaser.getTeaser().getUuid(), category.getCategoryInt());
adapter.add(teaser);
}
@Override
public void setNightMode() {
adapter.setNightMode(isNightMode);
newsRecycler.setBackgroundColor(getCurrentBackgroundColor());
}
@Override
public void hideProgress() {
refresh.setRefreshing(false);
}
@Override
public void showProgress() {
refresh.setRefreshing(true);
}
}