У меня, кажется, есть утечка памяти, и я не уверен, как исправить. Я прочитал все обучающие материалы и примеры ImageSwitcher на android.com, но все они, похоже, имеют дело с чертежами, которые уже находятся в папке drawables. Мой код позволяет пользователю делать одну или две фотографии с помощью своей камеры, сохранять изображения на SD и использовать обратный переключатель для «переворачивания» изображений.Android ImageSwitcher: вне памяти Ошибка при установкеImageURI
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 (это), и это кажется прекрасным, поскольку целью ImageSwitcher является переход между двумя изображениями. Мне интересно, есть ли лучший способ переключить изображения, кроме SetImageUri(). Я не вижу, чтобы я мог просачиваться или что может вызвать проблему. Я не вижу нигде, что convertView может даже использоваться. Есть ли способ кэшировать изображения из Uri? Вызывается перезагрузка изображений каждый раз .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 с использованием другой вытяжки. Я не вижу, как использование SoftReference могло бы помочь, так как теперь я сбой при начальной загрузке.
Спасибо за ваш ответ. Ты прав. У меня нет конвертирования в приведенном выше, но я говорил, что не мог даже увидеть, как в этом случае будет использоваться переработанное представление (convertView). Я читал, что сохранение растровых изображений в памяти было потенциально опасным для памяти. Я дам BitmapFactory выстрел и посмотрю, поможет ли это, особенно с помощью WeakReference/SoftReference. Ура! – Shawn