Android 内存泄漏和GridView

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可以将该活动保留在内存中,直到它想要释放它为止(在其他活动中

我使用的是GridView和universalimageloader(1.8.6),似乎遇到了内存泄漏-尽管我可能误解了DDMS和MAT结果?这是我没有写的代码,但它是非常基本的-我们展示了大量照片,允许用户选择他们想要的照片,然后存储这些照片以供将来参考。代码似乎工作得很好,但在MAT“Leak Suspect”中,下面的GridView不断出现,每次占用的空间超过5 mb,即使我调用了活动的finish()。据我所知,Android可以将该活动保留在内存中,直到它想要释放它为止(在其他活动中也看到了这一点),但它似乎从未想要释放这个活动——即使我强制GC。“新线程”的分配看起来有点可疑,但这不会被调用活动发现吗

可能只是遗漏了一些明显的东西,但代码如下:

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