2010-01-15 6 views
5

Ich habe eine Liste von 70 Textelementen mit Bildsymbolen (die im Drawables-Ordner gespeichert sind). Wenn ich Anwendung zum ersten Mal starten und die Liste langsam scrollen - die Ausnahme tritt nicht auf.OutOfMemory-Ausnahme erscheint beim Scrollen der Liste der Bilder

Wenn die Anwendung zum ersten Mal gestartet wird, und ich blättere, um die Liste mit ‚Seitensprung‘ Aktion der folgende Ausnahme auftritt:

java.lang.OutOfMemoryError: bitmap size exceeds VM budget 
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:439) 
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:322) 
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:688) 
at android.content.res.Resources.loadDrawable(Resources.java:1710) 
at android.content.res.Resources.getDrawable(Resources.java:585) 

Danach, wenn ich die Anwendung mit DDMS töten, starten Sie es erneut und blättern es mit 'Schleudern' Aktion, Ausnahme tritt nicht auf. Die Ausnahme tritt nur auf, wenn die Anwendung das erste Mal installiert und gestartet wird.

Hier ist der Adapter I für die Liste verwenden:

public class AuthorAdapter extends ArrayAdapter<Author> { 

private ArrayList<Author> items; 
private Context context; 
private LayoutInflater inflater; 

public AuthorAdapter(Context context, int textViewResourceId, ArrayList<Author> items) { 
    super(context, textViewResourceId, items); 
    this.items = items; 
    this.context = context; 
    inflater = LayoutInflater.from(this.context); 
} 

static class ViewHolder { 
    ImageView authorFace; 
    TextView authorName; 
    TextView authorWho; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 

    ViewHolder holder; 

    if (convertView == null) { 
     convertView = inflater.inflate(R.layout.autor_data, null); 

     holder = new ViewHolder(); 
     holder.authorFace = (ImageView) convertView.findViewById(R.id.authorFaceImageView); 
     holder.authorName = (TextView) convertView.findViewById(R.id.authorNameTextView); 
     holder.authorWho = (TextView) convertView.findViewById(R.id.authorWhoTextView); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    Author author = items.get(position); 
    if (author != null) { 
     if (holder.authorFace != null) { 
      String faceFileName = author.getFace(); 
      String facePlaceName = context.getPackageName() + ":drawable/" + faceFileName.subSequence(0, faceFileName.lastIndexOf(".")); 
      int faceFileId = context.getResources().getIdentifier(facePlaceName, null, null); 
      holder.authorFace.setImageResource(faceFileId); 
     } 
     if (holder.authorName != null) { 
      holder.authorName.setText(author.getName()); 
     } 
     if (holder.authorWho != null) { 
      holder.authorWho.setText(author.getWho()); 
     } 
    } 
    return convertView; 
} 

}

Gibt es eine Möglichkeit, die Ausnahme zu vermeiden? Sollte ich die Ausnahme fangen und den Speicher irgendwie entkommen?

Irgendwelche Ratschläge, wie dies zu erreichen ist?

Danke.

+0

Wie groß sind Ihre Bilder –

+0

Liste Artikel Bilder sind über je 3KB. Ich benutze zwei Aktivitäten (Haupt und Liste). Aktivitätshintergrundbilder sind jeweils etwa 60 KB. Außerdem gibt es Bilder, die ich für UI-Steuerelemente verwende, insgesamt etwa 100 KB. Kann es ein Simulatorproblem sein? Leider kann ich meine App im Moment nicht auf dem Gerät testen. – Zzokk

Antwort

3

Sie können keine java.lang.OutOfMemoryError fangen. Sie sind ziemlich fatal.

Jetzt sagen Sie, dass das Problem nur auftritt, wenn Sie Ihre Anwendung zum ersten Mal ausführen. Das lässt mich denken, dass das Problem nicht mit dem View-Code ist. Wenn ein Benutzer eine ressourcenintensive Ansicht wechselt, kann er viel Speicher verwenden, aber wie Sie sagen, funktioniert Ihre Anwendung normalerweise einwandfrei.

Also - welche Initialisierung machen Sie das erste Mal, wenn Sie Ihre Anwendung ausführen? Ist es möglich, dass eine der erstmalig ausgeführten Aufgaben Speicherverlust hat, was bedeutet, dass nicht mehr genug Platz für die Verwendung Ihrer Ansicht ist?

+0

Eigentlich initialisiere ich keine Bilder beim ersten Start der Anwendung. Alle meine Bilder werden im Ordner "Drawables" gespeichert. Ich habe nur den Adapter für die Liste festgelegt. In der getView() - Methode des Adapters habe ich das Bild für jedes Listenelement festgelegt (siehe obigen Code): halter.authorFace.setImageResource (faceFileId); Wie ich verstehe, getView() -Methode wird jedes Mal aufgerufen, wenn ein Listenelement auf dem Telefonbildschirm angezeigt wird. Wahrscheinlich, wenn ich schnell die Liste scrolle, hat der Cache keine Zeit zum Recyceln. Wenn ich langsam die Liste scrolle, wird keine Ausnahme beobachtet. – Zzokk

+2

Ich habe mich gefragt, ob es ein anderes Initialisierungsverhalten gibt, das Speicher verliert, so dass es keinen Platz auf dem Heap für viele Bilder gibt, wenn Sie schnell durch die Ansicht scrollen. Dies würde erklären, warum das Problem nur auftritt, wenn Sie Ihre Anwendung zum ersten Mal ausführen. –

+1

Vereinbaren Sie mit Dave, ich würde anfangen zu sehen, was machst du das erste Mal, wenn Sie die App starten vs normalen Startup. Du hältst an etwas Großem während deiner ersten Init der App fest. –

Verwandte Themen