Android 内存泄漏和GridView
我使用的是GridView和universalimageloader(1.8.6),似乎遇到了内存泄漏-尽管我可能误解了DDMS和MAT结果?这是我没有写的代码,但它是非常基本的-我们展示了大量照片,允许用户选择他们想要的照片,然后存储这些照片以供将来参考。代码似乎工作得很好,但在MAT“Leak Suspect”中,下面的GridView不断出现,每次占用的空间超过5 mb,即使我调用了活动的finish()。据我所知,Android可以将该活动保留在内存中,直到它想要释放它为止(在其他活动中也看到了这一点),但它似乎从未想要释放这个活动——即使我强制GC。“新线程”的分配看起来有点可疑,但这不会被调用活动发现吗 可能只是遗漏了一些明显的东西,但代码如下:Android 内存泄漏和GridView,android,gridview,android-activity,memory-leaks,universal-image-loader,Android,Gridview,Android Activity,Memory Leaks,Universal Image Loader,我使用的是GridView和universalimageloader(1.8.6),似乎遇到了内存泄漏-尽管我可能误解了DDMS和MAT结果?这是我没有写的代码,但它是非常基本的-我们展示了大量照片,允许用户选择他们想要的照片,然后存储这些照片以供将来参考。代码似乎工作得很好,但在MAT“Leak Suspect”中,下面的GridView不断出现,每次占用的空间超过5 mb,即使我调用了活动的finish()。据我所知,Android可以将该活动保留在内存中,直到它想要释放它为止(在其他活动中
public class PhotoGalleryPickerActivity extends MyActivity {
private Boolean mMultiple = false;
GridView gridGallery;
Handler handler;
GalleryAdapter adapter;
ImageView imgNoMedia;
Button btnGalleryOk;
String action;
private ImageLoader imageLoader;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_gallery_picker);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle("Photo Gallery Capture");
Bundle extras = getIntent().getExtras();
mMultiple = extras.getBoolean("multiple");
initImageLoader();
init();
}
private void initImageLoader() {
try {
String CACHE_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/.temp_tmp";
new File(CACHE_DIR).mkdirs();
File cacheDir = StorageUtils.getOwnCacheDirectory(getBaseContext(), CACHE_DIR);
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.cacheOnDisc(true).imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565).build();
ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(
getBaseContext())
.defaultDisplayImageOptions(defaultOptions)
.discCache(new UnlimitedDiscCache(cacheDir))
.memoryCache(new WeakMemoryCache());
ImageLoaderConfiguration config = builder.build();
imageLoader = ImageLoader.getInstance();
imageLoader.init(config);
} catch (Exception e) {
Utilities.logException(e);
}
}
private void init() {
handler = new Handler();
gridGallery = (GridView) findViewById(R.id.gridGallery);
gridGallery.setFastScrollEnabled(true);
adapter = new GalleryAdapter(getApplicationContext(), imageLoader);
PauseOnScrollListener listener = new PauseOnScrollListener(imageLoader, true, true);
gridGallery.setOnScrollListener(listener);
if (mMultiple == true){
findViewById(R.id.llBottomContainer).setVisibility(View.VISIBLE);
gridGallery.setOnItemClickListener(mItemMulClickListener);
adapter.setMultiplePick(true);
}
else {
findViewById(R.id.llBottomContainer).setVisibility(View.GONE);
gridGallery.setOnItemClickListener(mItemSingleClickListener);
adapter.setMultiplePick(false);
}
gridGallery.setAdapter(adapter);
imgNoMedia = (ImageView) findViewById(R.id.imgNoMedia);
btnGalleryOk = (Button) findViewById(R.id.btnGalleryOk);
btnGalleryOk.setOnClickListener(mOkClickListener);
new Thread() {
@Override
public void run() {
Looper.prepare();
handler.post(new Runnable() {
@Override
public void run() {
adapter.addAll(getGalleryPhotos());
checkImageStatus();
}
});
Looper.loop();
};
}.start();
}
private void checkImageStatus() {
if (adapter.isEmpty()) {
imgNoMedia.setVisibility(View.VISIBLE);
} else {
imgNoMedia.setVisibility(View.GONE);
}
}
View.OnClickListener mOkClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
ArrayList<CustomGallery> selected = adapter.getSelected();
String[] photos = new String[selected.size()];
for (int i = 0; i < photos.length; i++) {
photos[i] = selected.get(i).sdcardPath;
}
Intent data = new Intent().putExtra("photos", photos);
if(photos.length == 0) {
data = null;
}
setResult(RESULT_OK, data);
finish();
}
};
AdapterView.OnItemClickListener mItemMulClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
adapter.changeSelection(v, position);
}
};
AdapterView.OnItemClickListener mItemSingleClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> l, View v, int position, long id) {
CustomGallery item = adapter.getItem(position);
String[] photos = new String[1];
photos[0] = item.sdcardPath;
Intent data = new Intent().putExtra("photos", photos);
setResult(RESULT_OK, data);
finish();
}
};
private ArrayList<CustomGallery> getGalleryPhotos() {
ArrayList<CustomGallery> galleryList = new ArrayList<CustomGallery>();
try {
String[] dirs = new String[1];
final String where = MediaStore.Images.Media.DATA + " not like ? ";
String mediaDir = GlobalState.getInstance().currentForm.mediaDirectory();
if (mediaDir != null) {
int slash = mediaDir.lastIndexOf("/");
dirs[0] = mediaDir.substring(0, slash) + "%";
}
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = null;
try {
if (mediaDir != null && mediaDir.trim().length() > 0) {
imagecursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, where, dirs, orderBy);
}
else {
imagecursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
}
if (imagecursor != null && imagecursor.getCount() > 0) {
while (imagecursor.moveToNext()) {
CustomGallery item = new CustomGallery();
int dataColumnIndex = imagecursor
.getColumnIndex(MediaStore.Images.Media.DATA);
item.sdcardPath = imagecursor.getString(dataColumnIndex);
galleryList.add(item);
}
}
}
catch (Exception ex) {
Utilities.logException(ex);
Utilities.logError("PhotoGalleryPickerActivity", "getGalleryPhotos : " + ex.getMessage());
}
finally {
if (imagecursor != null) {
imagecursor.close();
}
}
} catch (Exception e) {
Utilities.logException(e);
e.printStackTrace();
}
// show newest photo at beginning of the list
Collections.reverse(galleryList);
return galleryList;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
PhotoGalleryPickerActivity.this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
公共类PhotoGalleryPickerActivity扩展了MyActivity{
私有布尔值mmmultiple=false;
GridView gridGallery;
处理者;
厨房适配器;
ImageView媒体;
按钮btnGalleryOk;
弦作用;
私有图像加载器;
@凌驾
ActivityResult上的公共void(int请求代码、int结果代码、意图数据){
}
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u photo\u gallery\u picker);
ActionBar ActionBar=getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(“照片库捕获”);
Bundle extras=getIntent().getExtras();
mmmultiple=extras.getBoolean(“多”);
initImageLoader();
init();
}
私有void initImageLoader(){
试一试{
字符串CACHE_DIR=Environment.getExternalStorageDirectory().getAbsolutePath()+“/.temp_tmp”;
新文件(CACHE_DIR).mkdirs();
文件cacheDir=StorageUtils.getOwnCacheDirectory(getBaseContext(),CACHE_DIR);
DisplayImageOptions defaultOptions=新建DisplayImageOptions.Builder()
.cacheOnDisc(true).imageScaleType(imageScaleType.justice)
.bitmapConfig(Bitmap.Config.RGB_565).build();
ImageLoaderConfiguration.Builder=新建ImageLoaderConfiguration.Builder(
getBaseContext())
.defaultDisplayImageOptions(默认选项)
.discCache(新的未限制的缓存(cacheDir))
.memoryCache(新的WeakMemoryCache());
ImageLoaderConfiguration config=builder.build();
imageLoader=imageLoader.getInstance();
init(config);
}捕获(例外e){
公用事业.例外情况(e);
}
}
私有void init(){
handler=新的handler();
gridGallery=(GridView)findViewById(R.id.gridGallery);
gridGallery.setFastScrollEnabled(true);
适配器=新的GalleryAdapter(getApplicationContext(),imageLoader);
PauseonSrollListener=新的PauseonSrollListener(imageLoader,true,true);
setOnScrollListener(listener);
如果(mmmultiple==true){
findviewbyd(R.id.llBottomContainer).setVisibility(View.VISIBLE);
setOnItemClickListener(miteMulClickListener);
adapter.setMultiplePick(真);
}
否则{
findviewbyd(R.id.llBottomContainer).setVisibility(View.GONE);
setOnItemClickListener(mItemSingleClickListener);
adapter.setMultiplePick(假);
}
设置适配器(适配器);
imgNoMedia=(ImageView)findViewById(R.id.imgNoMedia);
btnGalleryOk=(按钮)findViewById(R.id.btnGalleryOk);
setOnClickListener(mOkClickListener);
新线程(){
@凌驾
公开募捐{
Looper.prepare();
handler.post(新的Runnable(){
@凌驾
公开募捐{
adapter.addAll(getGalleryPhotos());
checkImageStatus();
}
});
loop.loop();
};
}.start();
}
私有void checkImageStatus(){
if(adapter.isEmpty()){
设置可见性(View.VISIBLE);
}否则{
imgNoMedia.setVisibility(View.GONE);
}
}
View.OnClickListener mOkClickListener=new View.OnClickListener(){
@凌驾
公共void onClick(视图v){
ArrayList selected=adapter.getSelected();
String[]photos=新字符串[selected.size()];
对于(int i=0;i