Bitmap Size exeeds VM since I use Fragments
My problem is mostly like this: strange out of memory issue, and I thought I already solved this by calling recycle(). This Problem occurs in example in my ListView: each Element has 0 to 10 icons. I extended my Adapter to recycle all Bitmaps from convertView which works. after an Item was clicked, I'm showing a detail site which uses same BMP's than my List. But Developing goes on, and I have the need to show everything in Tabs. So my ListView and the DetailView should be shown in the same Tab. After struggling two days with "ActivityGroup" (which is deprecated btw) I decided to use compatibility-package and start programming my Activity which shows the List and the DetailActivity as Fragments. While it seems to work, that my ListViewAdapter recycles every Bitmap from convertView, It doesn't seem to work at my DetailView. Log is telling me that recycle is called, but after 2-3 DetailViews (depending on shown Bitmaps) I get the same old Error. This is my only Activity living inside the TabView:
public class FaultGroup extends FragmentActivity implements OnItemClickListener, OnBackStackChangedListener{
public static final String FRAGMENT_LIST_TAG = "FaultListFragment";
public static final String FRAGMENT_DETAIL_TAG = "FaultDetailFragment";
public static final String TAG = "FaultGroup";
private FragmentManager mFragmentManager;
private FragmentTransaction mTransaction;
private boolean mDetailsShown = false;
public void onCreate(Bundle icicle){
super.onCreate(icicle);
setContentView(R.layout.fragment_layout);
mFragmentManager = getSupportFragmentManager();
mFragmentManager.addOnBackStackChangedListener(this);
FaultReportListFragment fragment = new FaultReportListFragment();
mTransaction= mFragmentManager.beginTransaction();
mTransaction.add(R.id.fragment_container, fragment, FRAGMENT_LIST_TAG);
mTransaction.addToBackStack(null);
mTransaction.commit();
}
public void onResume(){
super.onResume();
LogCat.d(TAG, "onResume");
}
public void onDestroy(){
super.onDestroy();
LogCat.d(TAG, "onDestroy");
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
LogCat.d(TAG, "onItemClick");
DatabaseReport dbReport = (DatabaseReport)parent.getAdapter().getItem(position);
fiScheduleDeviationReport report = dbReport.read();
Bundle arguments = new Bundle();
arguments.putParcelable(FaultReportDetailFragment.KEY_REPORT_EXTRA, report);
FaultReportDetailFragment fragment = new FaultReportDetailFragment();
fragment.setArguments(arguments);
mDetailsShown = true;
mTransaction = mFragmentManager.beginTransaction();
mTransaction.replace(R.id.fragment_container, fragment, FRAGMENT_DETAIL_TAG);
mTransaction.addToBackStack(null);
mTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
mTransaction.commit();
}
@Override
public void onBackPressed(){
mDetailsShown = false;
super.onBackPressed();
/*
mTransaction = mFragmentManager.beginTran开发者_如何学Csaction();
mTransaction.remove(mFragmentManager.findFragmentByTag(FRAGMENT_DETAIL_TAG));
mTransaction.
mTransaction.commit();
*/
}
@Override
public void onBackStackChanged() {
// TODO Auto-generated method stub
}
}
I see in my Log that Android calls onDestroyView and onDestroy on my DetailFragment, but somehow it has to store SOMETHING. If I just scroll (which causes OOM Error if I don't recycle convertViews) I don't get errors. Only If I opened details once.
here are the Methods which recycles my bmps:
DETAILS:
public void onDestroyView(){
LogCat.d(TAG, "onDestroyView");
LinearLayout iconRow;
for (int i = 0; i < mIconInflationArea.getChildCount(); i++){
LogCat.d(TAG, "onDestroyView-> inflationAreaChilds: " + mIconInflationArea.getChildCount());
iconRow = (LinearLayout)mIconInflationArea.getChildAt(i);
for (int row = 0; row < iconRow.getChildCount(); row++){
LogCat.d(TAG, "onDestroyView iconRow childs: " + iconRow.getChildCount());
View v = iconRow.getChildAt(row);
if (v instanceof ImageView){
ImageView image = (ImageView)v;
Drawable d = image.getDrawable();
Bitmap bmp = null;
if (d instanceof SvgDrawable){
SvgDrawable svg = (SvgDrawable)d;
bmp = svg.getBitmap();
} else if (d instanceof BitmapDrawable){
BitmapDrawable bmpd = (BitmapDrawable)d;
bmp = bmpd.getBitmap();
}
if (bmp != null){
bmp.recycle();
}
}
}
iconRow = null;
}
mIconInflationArea.removeAllViews();
mMessage = null;
//System.gc();
super.onDestroyView();
}
ADAPTER:
private void recycleBmpsFromConvertView(LinearLayout iconArea){
for (int i = 0; i < iconArea.getChildCount(); i++){
View v = iconArea.getChildAt(i);
if (v instanceof LinearLayout){
LinearLayout row = (LinearLayout)v;
for (int j = 0; j < row.getChildCount(); j++){
View candidate = row.getChildAt(j);
if (candidate instanceof ImageView){
ImageView image = (ImageView)candidate;
Drawable d = image.getDrawable();
Bitmap bmp = null;
if (d instanceof SvgDrawable){
SvgDrawable svg = (SvgDrawable)d;
bmp = svg.getBitmap();
} else if (d instanceof BitmapDrawable){
BitmapDrawable bmpd = (BitmapDrawable)d;
bmp = bmpd.getBitmap();
}
if (bmp != null){
bmp.recycle();
}
}
}
}
}
iconArea.removeAllViews();
}
Am I right to address that Problem at Fragments API, or is it just something else I miss?
EDIT: It seems to me that I don't have a memory leak. this is what Log tells me:
09-20 17:51:34.578: DEBUG/dalvikvm(11394): GC_EXPLICIT freed 54K, 48% free 4600K/8839K, external 12673K/13427K, paused 93ms
09-20 17:51:54.906: DEBUG/dalvikvm(7904): GC_CONCURRENT freed 608K, 57% free 2902K/6599K, external 1625K/2137K, paused 2ms+7ms
09-20 17:52:00.316: DEBUG/dalvikvm(9634): GC_CONCURRENT freed 550K, 51% free 3242K/6599K, external 1625K/2137K, paused 2ms+7ms
09-20 17:52:12.574: DEBUG/dalvikvm(9634): GC_EXPLICIT freed 352K, 55% free 2998K/6599K, external 1625K/2137K, paused 60ms
09-20 17:52:19.601: DEBUG/dalvikvm(8082): GC_EXPLICIT freed 347K, 53% free 3086K/6535K, external 1625K/2137K, paused 61ms
09-20 17:52:24.609: DEBUG/dalvikvm(7904): GC_EXPLICIT freed 247K, 56% free 2947K/6599K, external 1625K/2137K, paused 64ms
09-20 17:52:53.410: DEBUG/dalvikvm(10578): GC_CONCURRENT freed 540K, 56% free 3007K/6727K, external 1625K/2137K, paused 2ms+9ms
09-20 17:53:05.523: DEBUG/dalvikvm(7904): GC_CONCURRENT freed 591K, 56% free 2952K/6599K, external 1625K/2137K, paused 15ms+2ms
09-20 17:53:35.156: DEBUG/dalvikvm(7904): GC_EXPLICIT freed 259K, 57% free 2895K/6599K, external 1625K/2137K, paused 74ms
09-20 17:53:54.378: DEBUG/dalvikvm(10578): GC_CONCURRENT freed 538K, 56% free 3005K/6727K, external 1625K/2137K, paused 2ms+10ms
09-20 17:54:00.242: DEBUG/dalvikvm(9634): GC_CONCURRENT freed 350K, 52% free 3217K/6599K, external 1625K/2137K, paused 1ms+3ms
09-20 17:54:05.378: DEBUG/dalvikvm(9634): GC_EXPLICIT freed 360K, 55% free 3018K/6599K, external 1625K/2137K, paused 53ms
09-20 17:54:14.785: DEBUG/dalvikvm(8082): GC_EXPLICIT freed 216K, 53% free 3086K/6535K, external 1625K/2137K, paused 58ms
09-20 17:54:16.171: DEBUG/dalvikvm(7904): GC_CONCURRENT freed 574K, 57% free 2899K/6599K, external 1625K/2137K, paused 14ms+2ms
Ok i found out it has nothing do do with Fragments. The bitmaps I use was just too large :)
精彩评论