2010-11-28 6 views
0

Ce que fait l'application est très simple. Il charge deux flux RSS et sur chaque flux RSS, il contient deux éléments avec un titre, une image et un lien. Et puis il télécharge les images, les enregistre dans un dossier local et les affiche. Donc, deux flux RSS, et 4 téléchargements d'images.Comportement incohérent lors du chargement d'images à l'aide d'AsyncTask

Pour cela, j'utilise AsyncTask. Ainsi, deux objets AsyncTasks sont appelés pour charger deux flux RSS et 4 AsyncTasks pour charger 4 images. Les problèmes surviennent quand il essaie de télécharger des images. Pour la première fois, ça fonctionne bien. mais si je continue à les recharger, parfois AsyncTask ne fait rien. Et parfois, il ne parvient pas à lire entréestream ... très bizarre.

Existe-t-il une règle qui me manque pour utiliser AsyncTask?

Voici les extraits de mon code.

public class TunesAppsWidgetProvider extends AppWidgetProvider { 

private Intent taService = null; 
private static boolean widgetEnabled = false; 

@Override 
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { 
    taService = new Intent(context, UpdateService.class); 
    context.startService(taService); 
} 

public static class UpdateService extends Service { 


    @Override 
    public void onStart(Intent intent, int startId) { 
     Log.d(Constants.TAG, "Service: onStart()"); 
     Context context = getApplicationContext(); 
     mViews = new RemoteViews(context.getPackageName(), R.layout.tunesappswidget); 

     thisWidget = new ComponentName(this, TunesAppsWidgetProvider.class); 
     manager = AppWidgetManager.getInstance(this); 

     buildFeedUpdate(); 

     this.stopSelf(); 
     Log.d(Constants.TAG, "Stop Service"); 
    } 

    public void buildFeedUpdate() { 
     Log.d(Constants.TAG, "buildFeedUpdate"); 
     Context context = getApplicationContext(); 

     feedParser_0 = new FeedParser(context, Constants.FEED_ID_0); 
     feedParser_1 = new FeedParser(context, Constants.FEED_ID_1); 

     feedTask_0 = new LoadFeedTask(); 
     feedTask_0.execute(
       new LoadFeedTask.Payload(
         feedParser_0, 
         UpdateService.this 
       ) 
     ); 

     feedTask_1 = new LoadFeedTask(); 
     feedTask_1.execute(
       new LoadFeedTask.Payload(
         feedParser_1, 
         UpdateService.this 
       ) 
     ); 
    } 

    public void buildCoverUpdate(byte feedID, List<Message> feedRSS, String operator) { 
     Context context = getApplicationContext(); 

     Log.d(Constants.TAG, "buildCoverUpdate: " + feedID); 
     try { 
      switch(feedID) { 
       case Constants.FEED_ID_0: 
         coverImage_0 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_0).getImageLink(), Constants.SLOT_0); 

      coverImageTask_0 = new LoadCoverImageTask(); 
         coverImageTask_0.execute(
          new LoadCoverImageTask.Payload(
            coverImage_0, 
            UpdateService.this 
          ) 
         ); 

         coverImage_1 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_1).getImageLink(), Constants.SLOT_1); 

         coverImageTask_1 = new LoadCoverImageTask(); 
          coverImageTask_1.execute(
           new LoadCoverImageTask.Payload(
            coverImage_1, 
            UpdateService.this 
           ) 
         ); 
        break; 

       case Constants.FEED_ID_1: 
         coverImage_2 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_0).getImageLink(), Constants.SLOT_2, operator); 
        coverImageTask_2 = new LoadCoverImageTask(); 
         coverImageTask_2.execute(
           new LoadCoverImageTask.Payload(
             coverImage_2, 
             UpdateService.this 
           ) 
         ); 

         coverImage_3 = new CoverImage(context, feedRSS.get(Constants.ITEM_IDX_1).getImageLink(), Constants.SLOT_3, operator); 
         bm_3 = coverImage_3.getDefaultCoverImage(); 
          coverImageTask_3 = new LoadCoverImageTask(); 
          coverImageTask_3.execute(
           new LoadCoverImageTask.Payload(
            coverImage_3, 
            UpdateService.this 
           ) 
         ); 
        break; 

       default: 
        break; 
      } 
     } 
     catch(Exception e) { 
      Log.d(Constants.TAG, "buildCoverUpdate: " + e.toString()); 
     } 
    } 

}

Et ci-dessous le code est pour l'image de chargement. Parfois, ce DoInBackground n'est jamais appelé même si 'execute' est appelé. Parfois, il est coincé sur 'Bitmap bitmap = BitmapFactory.decodeStream (in)' ici et ne jamais échapper.

protected LoadCoverImageTask.Payload doInBackground(LoadCoverImageTask.Payload... param) { 
    HttpURLConnection httpConn = null; 
    InputStream in; 
    File imageFile; 
    FileOutputStream fos; 
    int slotIdx = param[0].coverImage.getSlotIndex(); 
    System.setProperty("http.keepAlive", "false"); 

    try{ 
     URL fileURL = new URL(param[0].coverImage.getFileURL()); 
     httpConn = (HttpURLConnection) fileURL.openConnection(); 
     Log.d(Constants.TAG , "openConn: Slot " + slotIdx); 

     httpConn.setConnectTimeout(10000); 

     if(httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) { 
      Log.d(Constants.TAG , "200OK: Slot " + slotIdx + ": " + fileURL.toString()); 

      in = httpConn.getInputStream(); 
      imageFile = new File(param[0].coverImage.getFullFilePath()); 
      fos = new FileOutputStream(imageFile); 

      try { 
       Bitmap bitmap = BitmapFactory.decodeStream(in); 
       Log.d(Constants.TAG , "200OK: Slot " + slotIdx + " decodeStream(in);"); 
       if(bitmap.compress(Bitmap.CompressFormat.JPEG, 80, fos) == true) { 
        fos.flush(); 
        fos.close(); 
        in.close(); 
        Log.d(Constants.TAG , "200OK-decodeOK: Slot " + slotIdx); 
        param[0].result = Constants.TRUE; 
       } 
       else { 
        fos.flush(); 
        fos.close(); 
        in.close(); 
        Log.d(Constants.TAG , "200OK-decodeFail: Slot " + slotIdx); 
        param[0].result = Constants.FALSE; 
       } 
      } 
      catch(NullPointerException e) { 
       Log.d(Constants.TAG , "Slot " + slotIdx + ":" + e.toString()); 
       param[0].result = Constants.RETRY; 
      } 
     } 
     else { 
      Log.d(Constants.TAG , "Slot " + slotIdx + ":" + httpConn.getResponseCode()); 
      param[0].result = Constants.FALSE; 
     } 

    } catch(SocketTimeoutException e) { 
     Log.d(Constants.TAG , "Time Out: " + slotIdx + ":" + e.toString()); 
    } catch(Exception e) { 
     Log.d(Constants.TAG , "Slot " + slotIdx + ":" + e.toString()); 
     param[0].result = Constants.FALSE; 
    } 
    finally { 
     if(httpConn != null) httpConn.disconnect(); 
     Log.d(Constants.TAG , "Slot " + slotIdx + ":httpConn.disconnect"); 
    } 
    return param[0]; 
} 

Je suis coincé sur ce point pour quelques jours .. s'il vous plaît aider ...

Répondre

1

Peut-être que le problème est pas dans votre code. Il y a un bug dans BitmapFactory.decodeStream, et si vous utilisez InputStream de la connexion http, il ne charge pas toujours bien l'image.

Regardez http://code.google.com/p/android/issues/detail?id=6066 pour plus d'informations

solution simple qui fonctionne pour moi télécharge un données de contenu entier dans le tampon puis en utilisant la méthode BitmapFactory.decodeByteArray:

InputStream is = httpCon.getInputStream(); 
byte [] content = inputStreamToByteArray2(is); 
image = BitmapFactory.decodeByteArray(content, 0, content.length); 


public static final byte[] inputStreamToByteArray(InputStream is) throws IOException { 
    BufferedInputStream bis = new BufferedInputStream(is); 
    ByteArrayOutputStream buf = new ByteArrayOutputStream(); 
    int result = bis.read(); 
    while(result !=-1) { 
     byte b = (byte)result; 
     buf.write(b); 
     result = bis.read(); 
    } 
    return buf.toByteArray(); 
} 

ou si vous ne le faites pas vouloir lire par 1 octet:

public static final byte[] inputStreamToByteArray(InputStream is) throws IOException { 
    BufferedInputStream bis = new BufferedInputStream(is); 
    ByteArrayOutputStream buf = new ByteArrayOutputStream(); 
    byte[] buffer = new byte[256]; 
    int result = bis.read(buffer); 
    while(result > 0) { 
     buf.write(buffer, 0, result); 
     result = bis.read(buffer); 
    } 
    return buf.toByteArray(); 
} 
+0

Nous vous remercions de votre aide. Alors, que dois-je utiliser pour charger les images si inputtream de la connexion http ne fonctionne pas bien? – juniano

+0

Merci beaucoup pour ce code ... Je me cognais la tête contre le mur jusqu'à ce que je tombe sur ce post et ai vu qu'il y avait un bug dans le code BitmapFactory. Votre solution a fonctionné pour moi. – esilver

Questions connexes