我遇到了内存泄漏问题。
我有一个带有FragmentStatePagerAdapter
的片段,里面有一个片段(还有更多片段,我只留下一个用于测试)。
这个片段有RecyclerView和一些不同的ViewHolders。
例如,这是一个简单的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笔交易转发给了另一个片段而我的 ViewHolders
由于某种原因被重新创建了!
我认为这件事会导致我的内存泄漏。我不确定你想要哪个代码所以我放了一些适配器方法,以防你想看到它。
NewsListRecyclerAdapter
是我的适配器,执行下面的代码。注意只创建一次这个类的内容!。
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == Constant.TYPE_TEASER) {
View view = inflater.inflate(R.layout.item_teaser_recycler, parent, false);
return new TeaserViewHolder(view, reference, isNightMode);
} else if (viewType == Constant.TYPE_CURRENCY_HEADER) {
View view = inflater.inflate(R.layout.item_list_currency, parent, false);
return new CurrencyViewHolder(view, isNightMode);
} else if (viewType == Constant.TYPE_TEASER_VISITED) {
View view = inflater.inflate(R.layout.item_teaser_recycler, parent, false);
return new TeaserVisitedViewHolder(view, reference, isNightMode);
}
throw new RuntimeException(
"there is no type that matches the type " + viewType
+ " + make sure your using types correctly");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
NewsListItem item = sortedList.get(position);
if (holder instanceof TeaserVisitedViewHolder) {
((TeaserVisitedViewHolder) holder).bind(item);
} else if (holder instanceof TeaserViewHolder) {
((TeaserViewHolder) holder).bind(item);
} else if (holder instanceof CurrencyViewHolder) {
((CurrencyViewHolder) holder).bind(item.getCurrency());
} else {
throw new RuntimeException(
"there is no type that matches the type " + holder.getClass().getSimpleName()
+ " + make sure your using types correctly");
}
}
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);
}
}
我无法滑动碎片,因为我在ViewPager中只剩下一个framgent(只是为了测试)。
答案 0 :(得分:0)
您的片段有多少时间重新创建?当您使用ViewHolder
滑动时,可能会重新创建新的Fragment
来计算12 FragmentStatePagerAdapter
次,从而重新设置RecyclerView
,RecyclerAdapter
和ViewHolders
。
你还试过在查看堆之前使用Initiate GC
吗?他们可能GC
正在等待收集旧的已销毁的视图,但由于有足够的可用内存GC
尚未获得这些内容。