在我的情况下,我使用WebView来呈现和显示新闻细节,我想通过自己而不是WebView来处理新闻图像的下载和缓存。所以我使用Picasso作为我的图片库,如下所示:
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (!Utils.hasHoneycomb()||TextUtils.isEmpty(url)||url.startsWith("file://")) {
return super.shouldInterceptRequest(view, url);
}
if (!url.startsWith("http") || !url.endsWith(".jpg") || !url.endsWith(".jpeg") || !url.endsWith(".png") ) {
return super.shouldInterceptRequest(view, url);
}
WebResourceResponse response = null;
try {
final PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(out);
Picasso.with(Application.getInstance()).load(url).into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
if (bitmap != null) {
try {
out.write(StreamTool.bmp2ByteArray100(bitmap, false));
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
response = new WebResourceResponse("image/*", "UTF-8", in);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
但它不起作用,我知道 shouldInterceptRequest 在非UI线程中工作,Picassso
throw new IllegalStateException("Method call should happen from the main thread.");
所以我有两个问题:
更新(添加异常堆栈):
06-08 18:17:05.540 5137-6951/com.news.daily I/dalvikvm﹕ java.lang.IllegalStateException: Method call should happen from the main thread.
06-08 18:17:05.540 5137-6951/com.news.daily I/dalvikvm﹕ at com.squareup.picasso.Utils.checkMain(Utils.java:136)
06-08 18:17:05.540 5137-6951/com.news.daily I/dalvikvm﹕ at com.squareup.picasso.RequestCreator.into(RequestCreator.java:496)
06-08 18:17:05.540 5137-6951/com.news.daily I/dalvikvm﹕ at com.news.daily.widget.webview.WebViewClientDaily.shouldInterceptRequest(WebViewClientDaily.java:123)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.webkit.CallbackProxy.shouldInterceptRequest(CallbackProxy.java:1534)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.webkit.BrowserFrame.shouldInterceptRequest(BrowserFrame.java:972)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.webkit.WebSettingsClassic.nativeSync(Native Method)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.webkit.WebSettingsClassic.access$100(WebSettingsClassic.java:50)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.webkit.WebSettingsClassic$EventHandler$1.handleMessage(WebSettingsClassic.java:291)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.os.Handler.dispatchMessage(Handler.java:99)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.os.Looper.loop(Looper.java:137)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:1092)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ at java.lang.Thread.run(Thread.java:841)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ DALVIK THREADS:
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ (mutexes: tll=0 tsl=0 tscl=0 ghl=0)
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ "main" prio=5 tid=1 NATIVE
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ | group="main" sCount=0 dsCount=0 obj=0x419dc710 self=0x419c60f0
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ | sysTid=5137 nice=0 sched=0/0 cgrp=apps handle=1074810876
06-08 18:17:05.550 5137-6951/com.news.daily I/dalvikvm﹕ | state=S schedstat=( 3242900256 1453466203 12922 ) utm=238 stm=86 core=3
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #00 pc 0001c6ec /system/lib/libc.so (epoll_wait+12)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #01 pc 000153f1 /system/lib/libutils.so (android::Looper::pollInner(int)+92)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #02 pc 00015615 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #03 pc 000729ed /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #04 pc 00020c0c /system/lib/libdvm.so (dvmPlatformInvoke+112)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #05 pc 0005178b /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+398)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ #06 pc 00000214 /dev/ashmem/dalvik-jit-code-cache (deleted)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at android.os.MessageQueue.nativePollOnce(Native Method)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at android.os.MessageQueue.next(MessageQueue.java:132)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at android.os.Looper.loop(Looper.java:124)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at android.app.ActivityThread.main(ActivityThread.java:5450)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at java.lang.reflect.Method.invokeNative(Native Method)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at java.lang.reflect.Method.invoke(Method.java:525)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ at dalvik.system.NativeStart.main(Native Method)
06-08 18:17:05.560 5137-6951/com.news.daily I/dalvikvm﹕ [ 06-08 18:17:05.560 5137: 6951 I/dalvikvm ]
"AsyncTask #10" prio=5 tid=41 WAIT
答案 0 :(得分:2)
get()方法允许您使用后台线程来检索 你想直接的形象。不需要Target。
目前通过使用此解决方法调用into()总是有一个 很有可能使用后台线程来获取目标上的图像。
毕加索允许外部呼叫者调用是错误的 into()除主线程外。这些方法涉及观点 因此在Picasso 2.3中没有同步地回收和取消 我们添加了支票。 From official discussion
因此,您可以使用get()
方法而不是into()
,只能从UI线程调用它。您可以使用OkHttp作为Picasso的http客户端,因为它内置了缓存。您还可以通过拦截OkHttp中的查询来覆盖缓存规则。这两个图书馆一起玩得很好。
答案 1 :(得分:1)
这是我在结合@ Xiaozou的例子和@dasar的建议后得出的解决方案:
webView.setWebViewClient(new WebViewClient() {
@SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
final String mime = URLConnection.guessContentTypeFromName(url);
if (mime == null || !mime.startsWith("image")) {
return super.shouldInterceptRequest(view, url);
}
try {
final Bitmap image = Picasso.with(context).load(url).get();
ByteArrayOutputStream out = new ByteArrayOutputStream();
if (mime.endsWith("jpeg")) {
image.compress(Bitmap.CompressFormat.JPEG, 100, out);
} else if (mime.endsWith("png")) {
image.compress(Bitmap.CompressFormat.PNG, 100, out);
} else {
return super.shouldInterceptRequest(view, url);
}
InputStream in = new ByteArrayInputStream(out.toByteArray());
return new WebResourceResponse(mime, "UTF-8", in);
} catch (IOException e) {
Log.e(TAG, "Unable to load image", e);
return super.shouldInterceptRequest(view, url);
}
}
});
我没有使用PipedOutputStream
因为请求只会在Bitmap.compress
次调用中终止而不会抛出任何错误。