2012-05-15 8 views
1

Link.fuites de mémoire applications

Maintenant, j'ai une fuite de contexte dans mon projet et sur le lien, il explique très bien tout ce qui pourrait causer. Pour être honnête j'ai essayé d'enlever autant que possible qui a des variables de contexte mais j'ai un problème avec ma vue de grille et mon adapteur de base et j'ai vraiment besoin d'aide que j'ai batté ma tête au-dessus de ceci. Parfois, il m'échappe que les ordures collectées se montrent comme un ninja sur les autres classes.

Ma question: « Qu'est-ce que les gars vous suggérer que je devrais changer? » et "Que dois-je faire attention?"

Voici ce que je faisais: 1. créé une carte Hash pour mes images étirables 2. A créé un adaptateur de base pour le gridview 3. Mon code pour la classe loadCover

Carte statique privée ImageLocator = Collections .synchronizedMap (nouveau 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(); 
     } 
    } 
} 
+0

Je ne jetai, mais passer le ImageView dans la LoadCover peut causer des problèmes lorsque vous le gardez après qu'une activité a été détruite, vous aurez toujours votre Activité en mémoire – Blundell

+0

Dois-je le transformer en méthode? Pour qu'il soit écrasé à chaque fois sur le défilement? – sdfwer

+0

Vous connaissez votre seule implémentation de Runnable, cela ne signifie pas qu'elle fonctionne sur son propre Thread? – Blundell

Répondre

3

Je l'ai regardé votre code et en une manière refactorisé plus facile à gérer, il a fait quelques petites choses.

Votre faire un certain type de chargement d'images dans votre méthode de getView, cela prend trop de temps et doit être fait dans un AsyncTask, ou un gestionnaire avec un certain type de rappel.

Vous stockez ensuite ces bitmaps dans une carte statique qui restera en mémoire pour la durée de vie de votre application, c'est baaad et conserve des références à votre contexte lorsque vous créez les bitmaps. Je peux voir votre utilisation comme une sorte de cache d'image pour quand ils sont chargés, peut-être penser d'une manière différente si cela vous cause des erreurs de mémoire.

Voici votre code, refondus:

/** 
* @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 
    } 
} 

La classe adaptateur:

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; 
     } 
    } 

classe Domaine distinct bookInformation:

public class BookInformation { 

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

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

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

     public String getAuthor() { 
      return "author"; 
     } 
    } 
+0

Oui, vous avez raison. J'aurais dû le placer dans mon adaptateur de base pour le hashmap. Merci pour les informations concernant le gestionnaire de base de données. – sdfwer