【问题标题】:Picasso binding adapter 'a connection was leaked' messagePicasso 绑定适配器“连接被泄露”消息
【发布时间】:2018-05-25 04:08:33
【问题描述】:

我正在使用绑定适配器在回收站视图中加载图像。图像看起来很好。在快速滚动时,我注意到有时我会收到来自 Picasso 的“连接泄露”消息。

问题来自死图像链接,将我所有的图像 URL 硬编码为指向无处会为每个图像产生错误在将第一对图像滚动出屏幕后

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

代码基本相同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}"/>

分级

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'

我可以看到一些关于需要为标准 Okhttp 请求关闭连接的人的参考资料,但是看到 Picasso 加载调用是单行的,这怎么可能泄漏?

【问题讨论】:

  • 也许你应该在调用新请求之前取消之前的请求:Picasso.with(context).cancelRequest(imageView);

标签: android kotlin picasso android-image android-databinding


【解决方案1】:

Picasso 在后台使用 okhttp3 处理其网络请求。在这里查看 Picasso 的 NetworkRequestHandler 类的代码:https://github.com/square/picasso/blob/0728bb1c619746001c60296d975fbc6bd92a05d2/picasso/src/main/java/com/squareup/picasso/NetworkRequestHandler.java

有处理okhttp请求的加载函数:

@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);
  }

我对毕加索项目不太熟悉,但似乎响应主体对象并非在所有情况下都关闭。你可能已经在 Picasso 中发现了一个错误,并且可能想在 picasso 的 github 上提出问题

【讨论】:

  • 谢谢,我在想我不太可能在 Picasso 中发现一些不正确的问题,但我注意到这在 Marshmallow 模拟器上不是问题(在 Oreo avd 上发现了问题),。明天会做更多的挖掘:)
【解决方案2】:

猜测,如果它与您的活动的上下文泄漏有关。试试 applicationContext

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多