메모리 누수가있는 것 같아 수정 방법이 확실하지 않습니다. android.com에서 ImageSwitcher 튜토리얼과 예제를 모두 읽었지만,이 모든 것들은 이미 드로어 블 폴더에있는 드로어 블을 처리하는 것처럼 보입니다. 내 코드를 통해 사용자는 카메라로 한 두 장의 사진을 찍어 이미지를 SD에 저장하고 imageswitcher를 사용하여 이미지를 뒤집을 수 있습니다.Android ImageSwitcher : Out of Memory setImageURI 오류
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가 활용 될지도 모르는 곳을 보지 않는다. Uri에서 이미지를 캐싱 할 수있는 방법이 있습니까? .setImageUri()가 호출 될 때마다 이미지가 다시로드됩니까? 그 메모리를 덤프 (또는 재사용) 할 수있는 방법이 있습니까? 이게 내 기억을 먹어 치우는거야?
는 무례하거나 무례 소리하지 않기,하지만 난 정말 방지 메모리를 참조하는 사람이 imageswitcher에 대한 JavaDoc을 기사 또는 링크를 누출하지 않고 도움을 선호? 메모리 누출 피하기 기사에는 "이 작업을해서는 안되는"몇 가지 내용이 나와 있지만 대신 "수행해야 할 작업"이 나와 있습니다. 이미 javadocs에 대한 링크가 있습니다. 나는 실제로 내가 잘못하고있는 것을 실제로 설명 할 수있는 사람을 찾고 있으며, Google 검색에서 상위 3 개 링크를 역 겨레하기보다는 (코드 명이 모호한 추상 학술 이론보다는 코드를 가장 잘 배웁니다) 코드로 더 나은 방향으로 나를 안내해줍니다. . :)
도움 주셔서 감사합니다! :)
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가 없지만,이 경우 convertView (재생 된 뷰)가 어떻게 사용되는지조차도 알 수 없다고 말하고있었습니다. 나는 메모리에서 비트 맵을 유지하는 것이 잠재적으로 메모리를 많이 차지한다는 것을 읽었다. BitmapFactory에 샷을 제공하고, 특히 WeakReference/SoftReference를 사용하여 도움이되는지 확인합니다. 건배! – Shawn