1

链接

现在我的项目中有一个上下文泄漏,并且在链接上它几乎解释了可能导致它的所有内容。

老实说,我试图尽可能多地删除具有上下文变量的内容,但我的网格视图和基本适配器有问题,我真的需要帮助,我一直在努力解决这个问题。有时它让我觉得它收集了垃圾,然后在其他课程中表现得像忍者。

我的问题:“你们建议我应该改变什么?” “我应该注意什么?”

这是我所做的: 1. 为我的可绘制图像创建一个哈希映射 2. 为 gridview 创建一个基本适配器 3. 我的 loadCover 类代码

私有静态地图 ImageLocator = Collections.synchronizedMap(new WeakHashMap());

private class BaseA extends BaseAdapter{
    private LayoutInflater inflater;

    public BaseA(Context context){
        inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        View row = convertView;
        viewHolder vh = new viewHolder();

        row = inflater.inflate(R.layout.book_row_view, null);       
        vh.authors = (TextView)row.findViewById(R.id.book_Author);
        vh.image = (ImageView)row.findViewById(R.id.icon);
        vh.date = (TextView)row.findViewById(R.id.Date);
        vh.Titles = (TextView)row.findViewById(R.id.Book_Title);
        vh.fileName = (TextView)row.findViewById(R.id.FileLocation);

        try{
            String temp = File_Name.get(position);
            vh.fileName.setText(temp);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

        Book_Information bi;
        bi = new Book_Information();
        bi = dbh.getData(File_Name.get(position));
        //Gets the right book information for all the items
        new LoadCover(vh.image, bi).run();
        if(bi.getBook_Author() != null || bi.getBook_Date() !=null || bi.getBook_Description() != null ||
                bi.getBook_Title() != null){

            vh.authors.setText(bi.getBook_Author());
            vh.date.setText(bi.getBook_Date());
            vh.Titles.setText(bi.getBook_Title());
        }                   
        return row;
    }

    public int getCount() {
        // TODO Auto-generated method stub
        return File_Name.size();
    }

    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

}



private class LoadCover implements Runnable{
    ImageView image; Book_Information bi;

    public LoadCover(ImageView image, Book_Information bi){
        this.image = image;
        this.bi = bi;
    }

    public void run() {
        // TODO Auto-generated method stub
        Drawable draw = ImageLocator.get(bi.getBook_File_Name());

        if(draw!=null){
            image.setImageDrawable(draw);
        }else{
            new UpdateImages(image, bi).run();
        }
        draw = null;
    }


}

private class UpdateImages implements Runnable{
    ImageView image;
    Book_Information book_info;

    public UpdateImages(ImageView imageView,  Book_Information bookInfo){
        this.image = imageView;
        this.book_info = bookInfo;
    }
    public void run(){
        try{
            Bitmap bm = getBitmap(book_info);
            FastBitmapDrawable fbd = new FastBitmapDrawable(bm);
            image.setImageDrawable(fbd);
            ImageLocator.put(book_info.getBook_File_Name(), fbd);
            bm = null;
        }catch (OutOfMemoryError e) {
            // TODO: handle exception
            ImageLocator.clear();
        }
    }
}
4

1 回答 1

3

我查看了您的代码并将其重构为更易于管理的方式,它指出了一些事情。

您在 getView 方法中执行某种类型的图像加载,这需要很长时间,应该在 ASyncTask 或具有某种类型回调的处理程序中完成。

然后,您将这些位图存储在一个静态映射中,该映射将在您的应用程序的整个生命周期中保留在内存中,这是 baaad,并在您创建位图时保留对您的上下文的引用。我可以看到您在加载它们时将其用作一种图像缓存,如果这导致您出现内存不足错误,也许可以考虑另一种方式。

这是您的代码,已重构:

/**
 * @author paul.blundell
 *         May 15, 2012
 */
public class MyAct extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        List<String> fileNames = new ArrayList<String>(); // Whatever filenames you get
        List<BookInformation> list = dbh.getData(fileNames); // However you get your data from the database (usually in a Service)

        BaseA base = new BaseA(inflater, list);

        // Do whatever with base
    }
 }

适配器类:

    public class BaseA extends BaseAdapter {

        // Having a static map means it lives the entire life of your application, your drawables should take a context
        // when they are being created therefore they have a reference to your Activity, and this is not being destroyed
        public static Map<String, Drawable> imageLocator = new WeakHashMap<String, Drawable>();

        private LayoutInflater inflater;
        private List<BookInformation> books;

        public BaseA(LayoutInflater inflater, List<BookInformation> books) {
            this.inflater = inflater;
            this.books = books;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            View rowView = convertView;
            ViewHolder vh = null;

            if(rowView == null){
                // Get new instance of our row view
                rowView = inflateView();
                // Hold the view in an object so it doesnt need to be re-fetched
                vh = new ViewHolder();

                vh.authors  = (TextView)  rowView.findViewById(R.id.book_author);
                vh.image    = (ImageView) rowView.findViewById(R.id.book_icon);
                vh.date     = (TextView)  rowView.findViewById(R.id.book_date);
                vh.titles   = (TextView)  rowView.findViewById(R.id.book_title);
                vh.fileName = (TextView)  rowView.findViewById(R.id.file_location);

                // Cache the view so it can be re-accessed later
                rowView.setTag(vh);
            } else {
                vh = (ViewHolder) rowView.getTag();
            }

            BookInformation book = books.get(position);
            vh.fileName.setText(book.getFileName());

            // Gets the right book information for all the items
            loadCover(vh.image, book.getFileName());

            if (book.getAuthor() != null){
                vh.authors.setText(book.getAuthor());
            }
            if(book.getDate() != null){
                vh.date.setText(book.getDate());
            }
            if(book.getTitle() != null){
                vh.titles.setText(book.getTitle());
            }

            return rowView;
        }

        private View inflateView() {
            return inflater.inflate(R.layout.view_book_row, null);
        }

        public int getCount() {
            return books.size();
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        private void loadCover(ImageView image, String filename) {
            Drawable draw = imageLocator.get(filename);

            if (draw == null) {
                draw = updateImage(filename);
            }
            imageLocator.put(filename, draw); // This is your problem keeping a reference to these drawables in a static map
            image.setImageDrawable(draw);
        }

        private Drawable updateImage(String filename) {
            Bitmap bm = getBitmap(filename);
            Drawable drawable = new BitmapDrawable(bm);
            return drawable;
        }

        private Bitmap getBitmap(String filename) {
            return null; // I don't know how you get a bitmap but you shouldn't do this in getView() , use a callback
        }

       private static class ViewHolder {
            public TextView fileName;
            public TextView titles;
            public TextView date;
            public ImageView image;
            public TextView authors;
        }
    }

单独的域类 bookInformation:

public class BookInformation {

        public String getFileName() {
            return "filename";
        }

        public String getTitle() {
            return "title";
        }

        public String getDate() {
            return "date";
        }

        public String getAuthor() {
            return "author";
        }
    }
于 2012-05-15T21:45:17.280 回答