我有一个浏览器,运行良好,但有一个内存泄漏。< br >我试图用堆分析和Eclipse memory analyser来寻找漏洞。< br >结果是我得到了几个ViewPager实例,并且在几次活动重新创建后没有在堆中释放位图。< br >我的代码中哪里会有泄漏原因?
这是片段,我在其中使用ViewPager并在一段时间后滚动项目:
private final int INTERVAL_TIME = 15000;
private ViewPager mViewPager;
private ViewPagerAdapter mAdapter;
private Handler mHandler;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_bottom, container, false);
......
mViewPager = (ViewPager) view.findViewById(R.id.pager);
mAdapter = new ViewPagerAdapter(getActivity(), bottomItems);
mViewPager.setAdapter(mAdapter);
mHandler = new Handler();
mHandler.postDelayed(UpdateTimeThread, INTERVAL_TIME);
return view;
}
private Runnable UpdateTimeThread = new Runnable() {
@Override
public void run() {
int position;
if (mViewPager.getCurrentItem() == mViewPager.getAdapter().getCount() - 1) {
position = 0;
} else {
position = mViewPager.getCurrentItem() + 1;
}
mViewPager.setCurrentItem(position, true);
mHandler.postDelayed(this, INTERVAL_TIME);
}
};
这是我的PagerAdapter,它可以在屏幕上同时显示3个项目(如果它们的format. equals("1"))或一次显示2个项目,以防其中一个是双倍大小的(format.equals("2"))
public class ViewPagerAdapter extends PagerAdapter {
private final List<JsonParsed.BottomItem> bottomItems;
private Activity activity;
public ViewPagerAdapter(Activity activity, List<JsonParsed.BottomItem> bottomItems) {
this.activity = activity;
this.bottomItems = bottomItems;
}
@Override
public int getCount() {
if (bottomItems.size() < 3) {
return 1;
}
return (int) Math.floor((float) bottomItems.size() / 3f);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.pager_item, container, false);
ImageView pic = (ImageView) itemView.findViewById(R.id.image_item);
ImageView pic2 = (ImageView) itemView.findViewById(R.id.image_item2);
ImageView pic3 = (ImageView) itemView.findViewById(R.id.image_item3);
pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
click(bottomItems.get(position * 3));
}
});
pic2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
click(bottomItems.get(position * 3 + 1));
}
});
pic3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
click(bottomItems.get(position * 3 + 2));
}
});
if (bottomItems.get(position * 3) != null) {
pic.setImageBitmap(BitmapFactory.decodeFile(bottomItems.get(position * 3).getPrev(activity).getAbsolutePath()));
if (bottomItems.get(position * 3).format.equals("1")) {
pic.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 2f));
} else if (bottomItems.get(position * 3).format.equals("2")) {
pic.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
}
} else {
pic.setVisibility(View.GONE);
}
if (bottomItems.size() > position * 3 + 1 && bottomItems.get(position * 3 + 1) != null) {
pic2.setImageBitmap(BitmapFactory.decodeFile(bottomItems.get(position * 3 + 1).getPrev(activity).getAbsolutePath()));
if (bottomItems.get(position * 3 + 1).format.equals("1")) {
pic2.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 2f));
} else if (bottomItems.get(position * 3 + 1).format.equals("2")) {
pic2.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
}
} else {
pic2.setVisibility(View.GONE);
}
if (bottomItems.size() > position * 3 + 2 && bottomItems.get(position * 3 + 2) != null) {
pic3.setImageBitmap(BitmapFactory.decodeFile(bottomItems.get(position * 3 + 2).getPrev(activity).getAbsolutePath()));
if (bottomItems.get(position * 3 + 2).format.equals("1")) {
pic3.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 2f));
} else if (bottomItems.get(position * 3 + 2).format.equals("2")) {
pic3.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1f));
}
} else {
pic3.setVisibility(View.GONE);
}
container.addView(itemView);
return itemView;
}
private void click(JsonParsed.BottomItem bottomItem) {
if (bottomItem.url != null && !bottomItem.url.isEmpty()) {
((MainActivity) activity).showWebView(bottomItem.url);
} else if (bottomItem.video != null && !bottomItem.video.isEmpty()) {
((MainActivity) activity).onPlayMedia(bottomItem.getVideo(activity).getAbsolutePath(), bottomItem.id, false);
}
}
@Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((LinearLayout) view);
}
非常感谢您的任何建议
编辑:
终于解决了泄漏。
正如Egor所指出的,主要泄漏是由Handler引起的,
因为它将引用保留在ViewPager实例上,因此实例不会被垃圾收集。
最后我只是使用了惰性解决方案-WeakHandler(开源库)。
我想它也是这样做的,正如Egors的文章
中所述,但使用它非常方便,因为您只是像往常一样使用它Handler:
WeakHandler(). postDelayed(……),仅此而已。
我还使用了位图的周引用,所有内存泄漏都消失了
处理程序
很可能是导致内存泄漏的处理程序。有一篇精彩的文章详细描述了这个问题,建议你使用弱引用
来解决这个问题。