2017-10-08 7 views
0

J'essaye de charger des images de manière asynchrone dans un CardPresenter dans Leanback comme ceci.okhttp3 throws NetworkOnMainThreadException lors du chargement asynchrone des images avec glide

public interface CustomImageModel { 
    String requestCustomUrl(int width, int height); 
} 

public static class CustomImageModelGrabber implements CustomImageModel { 

    public CustomImageModelGrabber() { 

    } 

    @Override 
    public String requestCustomUrl(int width, int height) { 
     OkHttpClient client = new OkHttpClient; 
     Request request = new Request.Builder().url(image_url).build(); 
     return client.newCall(request).execute().body().string(); 
    } 
} 

public static class CustomImageUrlLoader extends BaseGlideUrlLoader<CustomImageModel> { 
    public CustomImageUrlLoader(Context context) { 
     super(context); 
    } 

    @Override 
    protected String getUrl(CustomImageModel model, int width, int height) { 
     return model.requestCustomUrl(); 
    } 
} 

Dans CardPresenter.java

@Override 
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { 

    CustomImageModel customImageRequest = new CustomImageModelGrabber(); 

    Glide 
      .with(context) 
      .using(new CustomImageUrlLoader(context)) 
      .load(customImageRequest) 
      .into(imageView1); 
} 

Malheureusement, cela ne fonctionne pas comme prévu. Seules quelques images sont chargées correctement dans le présentateur de la carte, mais la plupart d'entre eux ne sont pas, et l'erreur suivante est levée:

android.os.NetworkOnMainThreadException 
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303) 

Il est tout à fait au hasard qui travaillent et qui ne le font pas.

J'ai également essayé de définir le mode strict dans MainActivity.java.

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
StrictMode.setThreadPolicy(policy); 

Bien que cette solution se charge correctement toutes les images et ne jette pas NetworkOnMainThreadException erreurs, il est livré avec des problèmes énormes de performance. Le défilement devient lent et lag, me montrant le message suivant:

I/Choreographer: Skipped 182 frames! The application may be doing too much work on its main thread. 

est-il une solution pour rendre la charge d'images de manière asynchrone, tout en conservant un bon et une bonne performance?

+1

Je crois que cette ligne 'client.newCall (demande) .Execute() corps() de chaîne();' est une exécution synchrone d'un.. demande réseau et provoque votre problème. – peitek

+0

vous avez raison ... J'ai utilisé ce code parce que je pensais que 'BaseGlideUrlLoader' est en cours d'exécution sur un thread de fond. –

Répondre

0

Mon approche était totalement fausse. Je pensais que BaseGlideUrlLoader s'exécute sur un thread de fond, mais ce n'est pas le cas.

Ainsi, le code pour aller est le suivant:

@Override 
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) { 

    final ImageCardView cardView = (ImageCardView) viewHolder.view; 

    OkHttpClient client = new OkHttpClient; 
    Request request = new Request.Builder().url(image_url).build(); 


    client.newCall(request).enqueue(new Callback() { 
     @Override public void onFailure(Call call, IOException e) { 
     e.printStackTrace(); 
     } 

     @Override public void onResponse(Call call, Response response) throws IOException { 
     try (ResponseBody responseBody = response.body()) { 
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); 


      String imageFromResponse = responseBody.string(); 
      // do whatever is needed to get the image (i.e JSON-handling) 

      Handler mainHandler = new Handler(Looper.getMainLooper()); 
      Runnable myRunnable = new Runnable() { 
       @Override 
       public void run() { 
        Glide.with(cardView.getContext()) 
          .load(imagefromResponse) 
          .error(mDefaultCardImage) 
          .into(cardView.getMainImageView()); 
       } 
      }; 
     } 
    }); 


}