在 AsyncTask 中使用 Picasso 从 URL 获取位图

Posted

技术标签:

【中文标题】在 AsyncTask 中使用 Picasso 从 URL 获取位图【英文标题】:Getting bitmap from URL using Picasso in AsyncTask 【发布时间】:2016-10-02 16:16:29 【问题描述】:

编辑:我已修复“方法调用...”错误。现在我的主要问题实际上是从我的 URL 加载位图。我显然没有正确处理它,当我尝试使用 PIcasso 的 .get() 方法时,我得到了 java.lang.OutOfMemoryError

最好的方法是什么?我什至不需要整个图像,只需要一个中心裁剪来填充我设备上的壁纸。但是如果不先加载它,我就无法裁剪它,这是我的问题。


所以我尝试使用 Picasso 从给定 URL 获取位图,然后在其顶部绘制文本并将其设置为我的墙纸背景。我目前正在尝试从 AsyncTask 中的 onPostExecute 执行此操作。我得到的错误是:

java.lang.IllegalStateException: Method call should not happen from the main thread.

导致问题的代码行是:

Bitmap bitmap = Picasso.with(myContext)
                .load(url + ".jpg")
                .fit()
                .centerCrop()
                .get();

以及整个 onPostExcute 函数:

protected void onPostExecute(String url) 

    ImageView imageView = (ImageView) rootView.findViewById(R.id.preview);
    try 
        Bitmap bitmap = Picasso.with(myContext)
                .load(url + ".jpg")
                .fit()
                .centerCrop().get();

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        paint.setColor(Color.RED); //Text Color
        paint.setStrokeWidth(72); //Text Size
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); //Text Overlapping Pattern

        canvas.drawBitmap(bitmap, 0, 0, paint);
        canvas.drawText("Test...", 10, 10, paint);

        ((ImageView) rootView.findViewById(R.id.preview)).setImageBitmap(bitmap);
        WallpaperManager wallpaperManager = WallpaperManager.getInstance(myContext);
        //wallpaperManager.suggestDesiredDimensions(width, height);
        wallpaperManager.setBitmap(bitmap);

        Toast.makeText(myContext, "Wallpaper set successfully.", Toast.LENGTH_SHORT).show();
    
    catch (Exception e) 
        android.util.Log.e(TAG, "Failed to set wallpaper", e);
    

我什至无法测试所有画布/绘画代码以查看它是否有效。如果您也发现其中有任何问题,请告诉我。非常感谢任何和所有提示。谢谢。

【问题讨论】:

检查这是否有帮助 ***.com/a/27180835/2686502 毕加索为你做异步,你为什么在上面使用AsyncTask?如果你想将毕加索与你的异步任务结合起来,你所做的必须部分进入doInBackgroundMethod。返回加载和修改后的图片,并设置在onPostExecute中。 【参考方案1】:

只需将@jayeshsolanki93 和@zapl cmets 放在一起即可。您收到该错误是因为您在主线程上从Picasso 调用方法get()get() 是一种同步方法,因此会出现错误。你有两个选择:

    get() 的调用移动到AsyncTaskdoInBackground 方法,然后在onPostExecute 上执行所有画布操作。

    充分利用 Picasso 并使用已有的异步方法并执行以下操作:

    Picasso.with(context).load(url).into(new Target() 
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) 
            Log.i(TAG, "The image was obtained correctly, now you can do your canvas operation!");
    
        
    
        @Override
        public void onBitmapFailed(Drawable errorDrawable) 
            Log.e(TAG, "The image was not obtained");
        
    
        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) 
            Log.(TAG, "Getting ready to get the image");
            //Here you should place a loading gif in the ImageView to
            //while image is being obtained.
        
    );
    

【讨论】:

我在 AsyncTask 中使用 Picasso 的原因是我有一些网络代码用于获取要传递给 Picasso 的 URL。你们帮我解决了主线程问题(仍在学习),但现在我正在处理 java.lang.OutOfMemoryError 由于未能正确调整传入图像的大小。我正在尝试使用不起作用的 .resize(w,h).centerCrop().get() 。有什么想法吗?

以上是关于在 AsyncTask 中使用 Picasso 从 URL 获取位图的主要内容,如果未能解决你的问题,请参考以下文章

Android图片下载以及缓存框架

Picasso中的缓存无效

Picasso:设置旧版本的 OkHttp3

在 android studio 中使用 AsyncTask 从套接字读取数据

使用 AsyncTask 从 JSON 中获取数据

如果使用 Asynctask 将 URL 存储在 ArrayList 中,如何从服务器下载图像?