2016-11-07 7 views
0

Ich lade einige Bilder von meinem Server herunter und benutze sie in einer Listview. Nachdem ich bestätigt habe, dass die Bilder tatsächlich heruntergeladen wurden (über einen Dienst), lade ich sie mit BitmapFactory.decodeFile() in ein Bitmap-Objekt. Die Funktion gibt intermittierend null zurück.BitmapFactory.decodeFile gibt null intermittierend zurück

Wenn ich das Fragment aktualisiere, werden Bilder ordnungsgemäß in Bitmap geladen. Ich habe das meistens nach dem ersten Download beobachtet, obwohl das nicht konsistent ist. Falls das Bild bereits heruntergeladen wurde, wird dies manchmal beobachtet. Hier

ist der Code Ich verwende:

@Override 
    public void run() { 

     while (!downImageFile.exists()) { 

      try { 
       Thread.sleep(1000); // Waits for 1 second (1000 milliseconds) 
      } catch (InterruptedException e) { 
       Log.e(LOG_TAG, "Exception", e); 
      } 
     } 
     Log.v(LOG_TAG,"Image downloaded now "+downImageFile.getAbsolutePath()); 
     //String updateWords = updateAuto(); // make updateAuto() return a string 
     imageView.post(new Runnable() { 
      @Override 
      public void run() { 
        Bitmap bm = BitmapFactory.decodeFile(downImageFile.getAbsolutePath()); 
        if(bm==null){ 
         Log.v(LOG_TAG,"Buzz image is null. Size is "+downImageFile.length()+" "+downImageFile.getAbsolutePath()); 
        } 
        imageView.setImageBitmap(bm); 
       } 
       imageView.setVisibility(View.VISIBLE); 
     }); 
    } 

Hier sind die entsprechenden Protokolle:

11-08 01:32:41.290 32245-32245/com.halobee.main D/skia: --- decoder->decode returned false 
11-08 01:32:41.290 32245-32245/com.halobee.main V/BeaconCustomList: Buzz image is null. Size is 255458 /data/user/0/com.halobee.main/files/buzz/hbuzz_b251149098404ebeb1198a5ac03087af20161107110912.jpg 

Dies kann kein OutOfMemory Problem sein, da keine derartigen Protokolle gedruckt werden und das Problem ist, wechselnd. Ich habe die Dateigröße nur gedruckt, um ihre Existenz zu bestätigen, und es ist auch ein gültiger Wert. Darüber hinaus ist das Problem bei einigen Geräten und nicht bei allen Geräten reproduzierbar. Ich lade das Bild in einem separaten Thread und nicht auf dem Hauptthread.

+0

Ähm, diese 'while' Schleife ist gruselig. Nur weil die Datei * existiert * heißt das nicht, dass die Datei * komplett geschrieben * wird. Verwenden Sie einen Ereignisbus oder etwas, damit der Dienst die UI-Ebene benachrichtigt, wenn das Bild heruntergeladen und vollständig gespeichert wurde. – CommonsWare

+0

Diese Zeile 'while (! DownImageFile.exists())' prüft, ob eine Datei existiert, gibt es irgendeine Garantie, dass alle Bytes des Bildes in die Datei geschrieben wurden, bevor sie die while-Schleife unterbricht und versucht, sie zu entschlüsseln? –

+0

Wenn dies asynchron gehandhabt wird, sollte keine Schleife erforderlich sein, da das Blockieren kein Problem ist, da Sie nicht im Hauptthread sind. –

Antwort

0

1) Sie können eine Bibliothek verwenden, um Ihnen mit diesem Problem zu helfen wie Volley, Picaso und vielen anderen Android-Bibliotheken

2) Versuchen Pixeldaten aus dem Bitmap in den ‚intArray‘ Array, da dies kann zu kopieren mit größeren Dateien

// copy pixel data from the Bitmap into the 'intArray' array 
        bm.getPixels(intArray, 0, bm.getWidth(), 0, 0, bm.getWidth(), 
          bm.getHeight()); 
0

ich schlage vor, Sie verwenden eine externe Bibliothek wie Glide oder Picassa zu tun Bild herunterladen, Caching und Anzeige viel helfen. Wie auch immer, wenn Sie sich entscheiden, keine der Bibliotheken zu verwenden, schlage ich vor, dass Sie in Ihrem Netzwerkaufruf oder in der Komponente, die das Bild abruft, einen Listener erstellen und erst dann die Decodierung durchführen, nachdem Sie die Verfügbarkeit der Datei an Ihr Fragment gesendet haben.

0

Möglicherweise gibt es weitere Gründe, warum Ihre Bitmap null zurückgibt. Stellen Sie zunächst sicher, dass Sie die Berechtigungen WRITE_EXTERNAL_STORAGE und READ_EXTERNAL_STORAGE in Ihrem Manifest sowie die Internetberechtigungen angegeben haben. Außerdem gibt es einige Änderungen von Android 6 und höher (SDK 23). Versuchen Sie Ihr Ziel SDK in Ihrem build.gradle bis 22.

+1

Wenn Sie das OP lesen "Wenn ich das Fragment aktualisiere, werden die Bilder richtig in die Bitmap geladen" - wie könnte das ein Berechtigungsproblem sein? –

+0

Ich habe sicherlich die Berechtigungen gegeben. –

0
Bitmap.decodeFile(). 

Die Funktion null kehrt periodisch zu ändern.

Es wird das bei großen Bildern tun, wo die Bitmap für den verfügbaren Speicher zu groß werden würde.

Verwenden Sie kleinere Bilder.

+0

Wie ich bereits sagte, werden die gleichen Bilder nach der Aktualisierung geladen. Das ist also kein Problem. –

+0

Warum nicht? Inzwischen kann der GC mehr freien Speicher haben. Versuche es mit kleineren Bildern zu sehen. – greenapps