2017-08-12 3 views
1

Je veux récupérer des photos en arrière-plan en utilisant AsyncTask. Je reçois une photo sous forme de chaîne sous forme encodée en base64. Cependant, j'ai "L'application peut-être faire trop de travail sur son thread principal" message d'erreur.Lors de la récupération d'images à partir de json obtenir "L'application peut-être faire trop de travail sur son thread principal" erreur

Mon activité:

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, ItemClickHandler{ 
 

 
    private RecyclerView recyclerView; 
 
    private RecyclerViewAdapter adapter; 
 
    private LayoutManager layoutManager; 
 

 
    private ArrayList<Device> devices; 
 

 
@Override 
 
    protected void onCreate(Bundle savedInstanceState) { 
 
     super.onCreate(savedInstanceState); 
 
     setContentView(R.layout.activity_action_bar); 
 

 
     recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 
 
     recyclerView.setHasFixedSize(true); 
 

 
     layoutManager = new LinearLayoutManager(this); 
 
     recyclerView.setLayoutManager(layoutManager); 
 
     adapter = new RecyclerViewAdapter(devices, this); 
 
     recyclerView.setAdapter(adapter); 
 

 
     initImages(); 
 
    } 
 

 
    private void initImages() { 
 
     Thread thread = new Thread() { 
 
      @Override 
 
      public void run() { 
 
       for(int i = 0; i < devices.size(); i++){ 
 
        final int pos = i; 
 
        GetImageJSON getImage = new GetImageJSON(MainActivity.this){ 
 
         @Override 
 
         protected void onPostExecute(final String result) { 
 
          Log.d(TAG, result); 
 

 
          if(pos <= recyclerView.getLayoutManager().getChildCount()){ 
 
           adapter.updateItem(ImageManager.convertToBitmap(result), pos); 
 
          } 
 
         } 
 
        }; 
 
        getImage.execute(ConnectionConfig.getUserItemImage(devices.get(i).getId())); 
 
       } 
 
      } 
 
     }; 
 
     thread.start(); 
 
    } 
 
}

classe GetImageJSON:

public class GetDataJSON extends AsyncTask<String, Void, String> { 
 

 
    private static String charset = "UTF-8"; 
 

 
    @Override 
 
    protected String doInBackground(String... args) { 
 
     String result = parseJSONString(args[0]); 
 
     if(!result.isEmpty()){ 
 
      try{ 
 
       JSONObject json = new JSONObject(result); 
 
       JSONObject jsonObject = json.getJSONObject(ConnectionConfig.TAG_RESULT); 
 
       String base64String = jsonObject.getString("image"); 
 
       Log.d(TAG, base64String); 
 
       Bitmap bitmap = ImageManager.convertToBitmap(base64String); 
 
       bitmap = ImageManager.scaleDownBitmap(bitmap, context); 
 
       Log.d(TAG, "got result: " + result); 
 
       return ImageManager.convertBitMapToString(bitmap); 
 
      }catch (JSONException e){ 
 
       e.printStackTrace(); 
 
      } 
 
     } 
 

 
     return result; 
 
    } 
 

 
    public static String parseJSONString(String... args){ 
 
     String result = ""; 
 
     InputStream inputStream = null; 
 

 
     Log.d(TAG, args[0]); 
 
     try { 
 
      URL url = new URL(args[0]); 
 
      HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); 
 

 
      conn.setDoOutput(false); 
 
      conn.setRequestMethod("GET"); 
 
      conn.setRequestProperty("Accept-Charset", charset); 
 
      conn.setConnectTimeout(15000); 
 
      conn.connect(); 
 

 
      try { 
 
       InputStream in = new BufferedInputStream(conn.getInputStream()); 
 
       BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
 
       String line; 
 
       while ((line = reader.readLine()) != null) { 
 
        result += line; 
 
       } 
 
      } catch (IOException e) { 
 
       e.printStackTrace(); 
 
      } 
 

 
      conn.disconnect(); 
 
     } catch (Exception e) { 
 
      Log.d(TAG, "Exception", e); 
 
     } finally { 
 
      try{ 
 
       if(inputStream != null) 
 
        inputStream.close(); 
 
      }catch(Exception e){ 
 
       Log.d(TAG, e.getMessage()); 
 
      } 
 
     } 
 

 
     return result; 
 
    } 
 
}

Je ne pouvais pas trouver une solution. S'il vous plaît, suggérez n'importe lequel. Comment je peux optimiser le processus de récupération des données.

+1

vous initialisez 'devices' ArrayList? –

+0

Oui, je l'obtiens de l'activité précédente – Madina

+0

avez-vous essayé avec le nouveau Runnable() dans le Thread? comme 'Thread t1 = new Thread (nouveau Runnable() { public void run() { // code va ici }}); t1.start(); ' –

Répondre

1

Je ne peux pas dire à coup sûr sans une version de votre code exécutable, mais je suppose que d'avoir la ligne ImageManager.convertToBitmap(result) dans onPostExecute() est l'origine du problème « trop de travail sur fil conducteur ». Tout ce qui se passe dans onPostExecute() se passe sur le thread principal, donc vous voulez garder cette méthode aussi légère que possible. Comme SRB l'a suggéré, vous pouvez éviter cela en ayant doInBackground renvoyer le bitmap, au lieu d'une chaîne qui doit être reconvertie en bitmap. Notez que pour changer le type de retour, vous devrez changer String-Bitmap en deux endroits:

public class GetDataJSON extends AsyncTask<String, Void, Bitmap> { 

    @Override 
    protected Bitmap doInBackground(String... args) { 
     // TODO return the bitmap 
    } 

    //...the rest of your code 

} 

Sur une note séparée, on dirait qu'il ya place à l'amélioration dans votre code. Ce sont des choses qui ne sont pas directement liées à votre question, mais qu'il serait bon de comprendre.

  1. Lorsque vous appelez getImage.execute(), méthode doInBackground de la classe GetDataJSON sera exécutée. La méthode doInBackground s'exécute toujours sur le thread d'arrière-plan (voir la section «Les 4 étapes» here). Il n'y a donc aucune raison de créer un nouveau thread dans la méthode initImages(). L'un des avantages de l'utilisation d'une vue de recyclage est que vous n'avez pas besoin de tout charger lorsque la vue de recyclage apparaît à l'écran. S'il existe des vues hors écran, ces vues peuvent être créées lorsque l'utilisateur fait défiler vers elles. En récupérant toutes les images lorsque l'activité est créée, vous perdez cet avantage.

  2. Il existe des bibliothèques de chargement d'images telles que Picasso et Glide qui effectuent des recherches d'images d'arrière-plan pour vous. Je ne sais pas à quoi ressemble votre API Web, mais si vous le pouvez, utiliser une bibliothèque préexistante peut simplifier le traitement rapide de problèmes tels que les espaces réservés, la mise en cache, le redimensionnement, etc.

+0

Je n'aide pas. J'ai changé mon code. L'application complète est dans https://git.4u.uz/Madina-S/MyApplication – Madina

+0

Au lieu de créer un lien vers l'ensemble de votre application, pouvez-vous créer un exemple simple qui reproduit le problème, puis afficher les bits de code pertinents? Voir [this] (https://stackoverflow.com/help/mcve) pour plus de détails. – Michiyo