1
我使用NavigationDrawer瀏覽我的應用程序,此時Drawer包含一個具有ListView的片段(大約50行) 。按下時,每行顯示帶有4個選項卡的ViewPager(每個選項卡包含4個ImageView和一些文本)。現在,這裏的問題:當我從一個標籤到另一個刷卡,成長堆錯誤在logcat中顯示出來:Android,在片段內部加載多個ImageViews(使用UIL) - > Grow heap
04-12 12:53:25.810 9377-9377/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 13.650MB for 600016-byte allocation
04-12 12:53:25.850 9377-9377/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 15.937MB for 2400016-byte allocation
04-12 12:53:26.130 9377-9377/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 18.507MB for 1960016-byte allocation
04-12 12:53:30.865 9377-9651/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 19.175MB for 557584-byte allocation
04-12 12:53:31.470 9377-9439/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 19.693MB for 557584-byte allocation
04-12 12:53:32.305 9377-9439/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 20.348MB for 557584-byte allocation
04-12 12:53:34.225 9377-9441/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 21.794MB for 278800-byte allocation
04-12 12:53:41.455 9377-9441/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 23.446MB for 557584-byte allocation
04-12 12:53:44.650 9377-9651/com.mypd.wiki I/dalvikvm-heap﹕ Grow heap (frag case) to 24.002MB for 557584-byte allocation
的ListView聽衆:
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Bundle bundle = new Bundle();
bundle.putInt("id", position);
TabStripAdapter newFragment = new TabStripAdapter();
newFragment.setArguments(bundle);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
});
與適配器沿ViewPager:
public class TabStripAdapter extends Fragment {
CollectionPagerAdapter adapterViewPager;
ViewPager viewPager;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.models_list_adapter, container, false);
viewPager = (ViewPager) view.findViewById(R.id.pager);
adapterViewPager = new CollectionPagerAdapter(getFragmentManager());
viewPager.setAdapter(adapterViewPager);
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) view.findViewById(R.id.tabs);
tabs.setViewPager(viewPager);
return view;
}
public class CollectionPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<>();
public CollectionPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return 4;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Bundle bundle = getArguments();
Tab1 frag1 = new Tab1().newInstance();
frag1.setArguments(bundle);
return frag1;
case 1:
Bundle bundle1 = getArguments();
Tab2 frag2 = new Tab2().newInstance();
frag2.setArguments(bundle1);
return frag2;
case 2:
Bundle bundle2 = getArguments();
Tab3 frag3 = new Tab3().newInstance();
frag3.setArguments(bundle2);
return frag3;
case 3:
Bundle bundle3 = getArguments();
Tab4 frag4 = new Tab4().newInstance();
frag4.setArguments(bundle3);
return frag4;
default:
break;
}
return null;
}
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Tab1";
case 1:
return "Tab2";
case 2:
return "Tab3";
case 3:
return "Tab4";
default:
return "None";
}
}
}
}
這是怎麼我的標籤之一是這樣的:
public class Tab1 extends Fragment {
DisplayImageOptions options;
ImageView extraImg1;
ImageView extraImg2;
ImageView extraImg3;
ImageView extraImg4;
public Tab1 newInstance() {
return new Tab1();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.loading_audi)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.delayBeforeLoading(200)
.bitmapConfig(Bitmap.Config.RGB_565)
.imageScaleType(ImageScaleType.EXACTLY)
.considerExifParams(true)
.build();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab_strip_1, container, false);
// Bundle setup:
Bundle bundle = this.getArguments();
int position = bundle.getInt("id");
if(bundle.containsKey("id")){
position = bundle.getInt("id");
} else {
this.getActivity().finish();
}
// TextView setup:
TextView title = (TextView) view.findViewById(R.id.title);
title.setText("Tab1 design");
TextView description = (TextView) view.findViewById(R.id.tab1);
description.setText(Data.Tab1[position]);
// ImageView setup:
extraImg1 = (ImageView) view.findViewById(R.id.extraImg1);
ImageLoader.getInstance().displayImage(Data.TabA[position], extraImg1, options);
//
extraImg2 = (ImageView) view.findViewById(R.id.extraImg2);
ImageLoader.getInstance().displayImage(Data.TabB[position], extraImg2, options);
//
extraImg3 = (ImageView) view.findViewById(R.id.extraImg3);
ImageLoader.getInstance().displayImage(Data.TabC[position], extraImg3, options);
//
extraImg4 = (ImageView) view.findViewById(R.id.extraImg4);
ImageLoader.getInstance().displayImage(Data.TabD[position], extraImg4, options);
return view;
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onPause(){
super.onPause();
}
@Override
public void onResume(){
super.onResume();
}
// Here I try to recycle the ImageViews but I'm not sure I'm doing it right...
public static void recycleImagesFromView(View view) {
if(view instanceof ImageView) {
Drawable drawable = ((ImageView)view).getDrawable();
if(drawable instanceof BitmapDrawable)
{
BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable;
bitmapDrawable.getBitmap().recycle();
}
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
recycleImagesFromView(((ViewGroup) view).getChildAt(i));
}
}
}
@Override
public void onDestroy(){
super.onDestroy();
recycleImagesFromView(getView());
}
}
UIL配置:
public class UILApplication extends Application {
...
public static void initImageLoader(Context context) {
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
config.threadPriority(Thread.NORM_PRIORITY - 2);
config.threadPoolSize(3);
config.denyCacheImageMultipleSizesInMemory();
config.memoryCache(new WeakMemoryCache());
config.denyCacheImageMultipleSizesInMemory();
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
config.diskCacheSize(200 * 1024 * 1024);
config.tasksProcessingOrder(QueueProcessingType.LIFO);
config.writeDebugLogs(); // Remove for release app
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config.build());
}
}
我的猜測是,我的內存泄漏的地方,無論我有一個適當的方式來回收ImageViews,要麼我失去了一些東西。
對不起我的英語技能。
仍然得到成長堆錯誤,我昨天打了大部分由UIL提供的選項。 – Alec