Кажется, у меня утечка памяти, и я не уверен, как ее исправить. Я прочитал все учебные пособия и примеры по ImageSwitcher на android.com, но похоже, что все они имеют дело с рисованными объектами, которые уже находятся в папке drawables. Мой код позволяет пользователю делать одну или две фотографии своей камерой, сохранять изображения на SD-карте и использовать переключатель изображений, чтобы «переворачивать» изображения поверх.
public class CardViewImageActivity extends Activity implements ViewFactory {
private CardDBAdapter mDbHelper;
private String _cardImgGuidFront;
private String _cardImgGuidBack;
private Boolean frontShowing = false;
private Boolean hasFront = false;
private Boolean hasBack = false;
private Uri uriFront;
private Uri uriBack;
private int cardId;
private ImageSwitcher iSwitcher;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.card_view_image);
iSwitcher = (ImageSwitcher)findViewById(R.id.imageSwitcher);
iSwitcher.setFactory(this);
iSwitcher.setOnClickListener(SwitcherOnClick);
this.cardId = Integer.parseInt(getIntent().getExtras().getString(
"cardId")); //$NON-NLS-1$
getCardImageGuids(this.cardId);
if(_cardImgGuidFront != null)
{
hasFront = true;
uriFront = Uri.parse(Environment.getExternalStorageDirectory().toString() + "/" + _cardImgGuidFront + ".jpg");
}
if(_cardImgGuidBack != null)
{
hasBack = true;
uriBack = Uri.parse(Environment.getExternalStorageDirectory().toString() + "/" + _cardImgGuidBack + ".jpg");
}
if(hasFront && hasBack)
Toast.makeText(this, R.string.card_view_touch, Toast.LENGTH_SHORT).show();
if(hasFront)
{
iSwitcher.setImageURI(uriFront);
frontShowing = true;
}
else if(hasBack)
{
iSwitcher.setImageURI(uriBack);
frontShowing = false;
}
else
{
Toast.makeText(this, R.string.card_no_image, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onDestroy()
{
iSwitcher.setImageURI(null);
super.onDestroy();
}
public View makeView() {
ImageView iView = new ImageView(this);
iView.setScaleType(ImageView.ScaleType.FIT_CENTER);
iView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
return iView;
}
protected OnClickListener SwitcherOnClick = new OnClickListener()
{
@Override
public void onClick(View v)
{
if(frontShowing && hasBack)
{
iSwitcher.destroyDrawingCache();
iSwitcher.setImageURI(uriBack);
frontShowing = false;
}
else if(!frontShowing && hasFront)
{
iSwitcher.destroyDrawingCache();
iSwitcher.setImageURI(uriFront);
frontShowing = true;
}
else
{
}
}
};
private void getCardImageGuids(int cardId)
{
try
{
this.mDbHelper = new CardDBAdapter(this);
this.mDbHelper.open();
Cursor c = this.mDbHelper.fetchCard(this.cardId);
_cardImgGuidFront = c.getString(c
.getColumnIndex(CardDBAdapter.CARD_IMG_GUID_FRONT));
_cardImgGuidBack = c.getString(c
.getColumnIndex(CardDBAdapter.CARD_IMG_GUID_BACK));
}
catch(SQLiteException ex)
{
Toast.makeText(CardViewImageActivity.this, ex.toString(), Toast.LENGTH_LONG).show();
}
finally
{
this.mDbHelper.close();
this.mDbHelper = null;
}
}
}
Вышеприведенный код, кажется, иногда работает довольно хорошо. Тем не менее, я иногда получаю ошибку OutOfMemory. Теперь, насколько я понимаю из-за отладки, makeView () вызывается дважды, когда вызывается .setFactory (this), и это нормально, поскольку цель ImageSwitcher - переключаться между двумя изображениями. Мне интересно, есть ли лучший способ для переключения изображений, кроме SetImageUri (). Я не вижу нигде, где я могу протекать или что может быть причиной проблемы. Я нигде не вижу, чтобы convertView мог даже использоваться. Есть ли способ кешировать изображения с Ури? Изображения загружаются каждый раз, когда вызывается .setImageUri ()? Есть ли способ сбросить эту память (или повторно использовать)? Это то, что съедает мою память?
Не звучит неуважительно или грубо, но я бы действительно предпочел помочь, если бы кто-то не ссылался на статью Как избежать утечек памяти или ссылок на javadocs для imageswitcher? Статья Избегать утечек памяти показывает пару «вы не должны этого делать», но никогда не показывает, что вы «должны» делать вместо этого. У меня уже есть ссылки на Javadocs. Я ищу кого-то, кто мог бы на самом деле объяснить, что я делаю неправильно, и направить меня в лучшем направлении с помощью кода (я изучаю код лучше, чем смутные абстрактные академические теории), а не просто извергать топ-3 ссылок из поиска Google , :)
Спасибо за любую помощь! :)
EDIT: 10Feb2012
Поэтому я попытался загрузить Drawables, и НЕМЕДЛЕННО получил ошибку нехватки памяти, которая является БОЛЬШЕ, чем получение ошибки иногда с помощью .setImageUri (). Следующее содержит моды:
private Drawable front;
private Drawable back;
@Override
public void onCreate(Bundle savedInstanceState) {
...
Resources res = getResources();
...
if(_cardImgGuidFront != null)
{
hasFront = true;
String frontPath = Environment.getExternalStorageDirectory().toString() + "/" + _cardImgGuidFront + ".jpg";
front = new BitmapDrawable(res, frontPath);
}
if(_cardImgGuidBack != null)
{
hasBack = true;
String backPath = Environment.getExternalStorageDirectory().toString() + "/" + _cardImgGuidBack + ".jpg";
back = new BitmapDrawable(res, backPath);
}
Глядя на SoftReference, использование требует создания SoftReference с использованием другого drawable. Я не понимаю, как использование SoftReference могло бы помочь, так как я сейчас сбой при начальной загрузке.