2017-12-11 136 views
8

Używam adaptera wiążącego do ładowania obrazów w widoku recyklera. Obrazy wyglądają dobrze. Podczas szybkiego przewijania zauważyłem, że czasami otrzymuję komunikat "połączenie wyciekło" z Picassa.Adapter wiązania Picasso "połączenie miało wyciek" wiadomość

Problem pochodzi z linków martwego obrazu, kodowanie wszystkich moich adresów URL obrazu do punktu nigdzie nie powoduje błędu dla każdego obrazu po przewinięciu pierwszej pary z ekranu.

W/OkHttpClient: A connection to https://s3-eu-west-1.amazonaws.com/ was leaked. Did you forget to close a response body? 

Kod jest w zasadzie identyczny: to this sample.

BindingUtils.kt

object BindingUtils { 

@BindingAdapter("imageUrl") 
@JvmStatic 
fun setImageUrl(imageView: ImageView, url: String) { 
    Picasso.with(imageView.context).load(url).into(imageView) 
} 

xml

<ImageView 
android:id="@+id/imageview_merchant_background" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="@color/primary" 
android:scaleType="centerCrop" 
app:imageUrl="@{viewModel.background}"/> 

Gradle

implementation "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion" 
implementation "com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofitVersion" 
implementation "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion" 
implementation "com.squareup.okhttp3:logging-interceptor:$rootProject.okhttpLoggingVersion" 
implementation "com.squareup.picasso:picasso:$rootProject.picassoVersion" 

retrofitVersion = '2.3.0' 
okhttpLoggingVersion = '3.6.0' 
picassoVersion = '2.5.2' 

widzę kilka odniesień do osób potrzebujących do zamknięcia połączenia dla standardowych wniosków Okhttp ale skoro tego Picassa Wywołanie obciążenia jest jedno liniowe, w jaki sposób może to być nieszczelne?

+0

Może powinieneś anulować poprzedni wniosek, przed skontaktowaniem się nowe: Picasso.with (kontekst) .cancelRequest (ImageView); –

Odpowiedz

2

Pod maską Picasso używa okhttp3 do obsługi żądań sieci. Zobacz tutaj kod dla klasy Picassa NetworkRequestHandler: https://github.com/square/picasso/blob/0728bb1c619746001c60296d975fbc6bd92a05d2/picasso/src/main/java/com/squareup/picasso/NetworkRequestHandler.java

Istnieje funkcja obciążenia, który obsługuje takie okhttp żądanie:

@Override public Result load(Request request, int networkPolicy) throws IOException { 
    okhttp3.Request downloaderRequest = createRequest(request, networkPolicy); 
    Response response = downloader.load(downloaderRequest); 
    ResponseBody body = response.body(); 

    if (!response.isSuccessful()) { 
     body.close(); 
     throw new ResponseException(response.code(), request.networkPolicy); 
    } 

    // Cache response is only null when the response comes fully from the network. Both completely 
    // cached and conditionally cached responses will have a non-null cache response. 
    Picasso.LoadedFrom loadedFrom = response.cacheResponse() == null ? NETWORK : DISK; 

    // Sometimes response content length is zero when requests are being replayed. Haven't found 
    // root cause to this but retrying the request seems safe to do so. 
    if (loadedFrom == DISK && body.contentLength() == 0) { 
     body.close(); 
     throw new ContentLengthException("Received response with 0 content-length header."); 
    } 
    if (loadedFrom == NETWORK && body.contentLength() > 0) { 
     stats.dispatchDownloadFinished(body.contentLength()); 
    } 
    InputStream is = body.byteStream(); 
    return new Result(is, loadedFrom); 
    } 

nie jestem zbyt obeznany z projektem Picassa, ale wydaje się, że obiekt ciała odpowiedź nie jest zamknięty we wszystkich przypadkach. Mogłeś zauważony błąd w Picasso i może chcieć złożyć sprawę na Picassa github

+0

Dzięki, pomyślałem, że jest mało prawdopodobne, że mój stary zauważył coś niepoprawnego w Picassie, ale zauważyłem, że nie jest to problem na emulatorze Marshmallow (problem został zauważony w Oreo avd). jutro zrobię więcej kopania :) –

0

Dziki odgadnąć, jeśli ma nic zrobić z wyciekiem kontekście swojej działalności. Spróbuj z ApplicationContext

Picasso.with(imageView.context.applicationContext).load(url).into(imageView)