使用Picasso和Image Getter

时间:2014-08-08 00:54:21

标签: android image picasso

我正在构建一个聊天应用程序,我试图将图像附加到EditText,通过使用Picasso从URL获取图像,附加和ImageGetter将图像附加到EditText。但是,我在下面实现的内容不起作用,因为在使用应用程序时附加消息不显示任何内容(但消息确实显示在数据库中)。

我已经在不使用Picasso的情况下进行了测试,因为只需在应用程序中使用带有图像资源的ImageGetter就可以正常工作,只是不需要来自URL。

配置ImageGetter和/或append方法的正确方法是什么,以便此功能可以与Picasso一起使用?或者有更简单的方法吗?

追加方法:

public void appendToMessageHistory(final String username,
            final String message) {
        if (username != null && message != null) {

            Picasso.with(getBaseContext())
                    .load("http://localhost:3000/uploads/campaign/image/2/2.jpg")
                    .into(new Target() {

                        @Override
                        public void onPrepareLoad(Drawable arg0) {

                        }

                        @Override
                        public void onBitmapLoaded(Bitmap bitmap,
                                LoadedFrom arg1) {
                            Drawable drawImage = new BitmapDrawable(
                                    getBaseContext().getResources(), bitmap);

                            drawImage.setBounds(0, 0,
                                    drawImage.getIntrinsicHeight(),
                                    drawImage.getIntrinsicWidth());
                            messageHistoryText.append(Html.fromHtml("<b>"
                                    + username + ":" + "</b>" + "<br>"));
                            messageHistoryText.append(Html.fromHtml(message
                                    + "<hr>" + "<br>")
                                    + System.getProperty("line.separator") + "");

                            messageHistoryText.append(Html
                                    .fromHtml("<img src = '" + drawImage
                                            + "'/>",
                            imageGetter,
                            null));
                        }

                        @Override
                        public void onBitmapFailed(Drawable arg0) {

                        }
                    });

        }
    }

ImageGetter:

ImageGetter imageGetter = new ImageGetter() {
        Drawable imageUsed=null;

        @Override
        public Drawable getDrawable(String source) {

            Picasso.with(getBaseContext())
                    .load("http://localhost:3000/uploads/campaign/image/2/2.jpg")
                    .into(new Target() {

                        @Override
                        public void onPrepareLoad(Drawable arg0) {

                        }

                        @Override
                        public void onBitmapLoaded(Bitmap bitmap,
                                LoadedFrom arg1) {
                            Drawable drawImage = new BitmapDrawable(
                                    getBaseContext().getResources(), bitmap);

                            drawImage.setBounds(0, 0,
                                    drawImage.getIntrinsicHeight(),
                                    drawImage.getIntrinsicWidth());

                            imageUsed=drawImage;

                        }

                        @Override
                        public void onBitmapFailed(Drawable arg0) {

                        }
                    });

            return imageUsed;
        }

    };

4 个答案:

答案 0 :(得分:21)

我无法使用Picasso的目标......

我的解决方法是:

  • 使用AsyncTask进行并发
  • 使用Picasso的get()方法在AsyncTask的背景方法中加载图像同步

像这样:

public class PicassoImageGetter implements Html.ImageGetter {

final Resources resources;

final Picasso pablo;

final TextView textView;

public PicassoImageGetter(final TextView textView, final Resources resources, final Picasso pablo) {
    this.textView  = textView;
    this.resources = resources;
    this.pablo     = pablo;
}

@Override public Drawable getDrawable(final String source) {
    final BitmapDrawablePlaceHolder result = new BitmapDrawablePlaceHolder();

    new AsyncTask<Void, Void, Bitmap>() {

        @Override
        protected Bitmap doInBackground(final Void... meh) {
            try {
                return pablo.load(source).get();
            } catch (Exception e) {
                return null;
            }
        }

        @Override
        protected void onPostExecute(final Bitmap bitmap) {
            try {
                final BitmapDrawable drawable = new BitmapDrawable(resources, bitmap);

                drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

                result.setDrawable(drawable);
                result.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

                textView.setText(textView.getText()); // invalidate() doesn't work correctly...
            } catch (Exception e) {
                /* nom nom nom*/
            }
        }

    }.execute((Void) null);

    return result;
}

static class BitmapDrawablePlaceHolder extends BitmapDrawable {

    protected Drawable drawable;

    @Override
    public void draw(final Canvas canvas) {
        if (drawable != null) {
            drawable.draw(canvas);
        }
    }

    public void setDrawable(Drawable drawable) {
        this.drawable = drawable;
    }

}

希望这很有用。

答案 1 :(得分:5)

我建立在托马斯的回答上。我使用现有的Picasso方法在不同的线程上下载任何图像,并占用了占位符Drawables。

public class PicassoImageGetter implements Html.ImageGetter {
    private TextView textView = null;

    public PicassoImageGetter() {}

    public PicassoImageGetter(TextView target) {
        textView = target;
    }

    @Override
    public Drawable getDrawable(String source) {
        BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();

        Context context = FeedSurferApp.getContext();
        FeedSurferApp
                .getPicasso()
                .load(source)
                .error(ResourcesCompat.getDrawable(context.getResources(), R.drawable.connection_error, context.getTheme()))
                .into(drawable);

        return drawable;
    }

    private class BitmapDrawablePlaceHolder extends BitmapDrawable implements Target {
        protected Drawable drawable;

        @Override
        public void draw(final Canvas canvas) {
            if (drawable != null) {
                drawable.draw(canvas);
            }
        }

        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            if (textView != null) {
                textView.setText(textView.getText());
            }
        }

        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            setDrawable(new BitmapDrawable(FeedSurferApp.getContext().getResources(), bitmap));
        }

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {
            setDrawable(errorDrawable);
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {}
    }
}

答案 2 :(得分:1)

我找到了一种将ImageGetter与Picasso Target一起使用的方法:

    public Drawable getDrawable(String source) {

            final BitmapDrawablePlaceHolder result = new BitmapDrawablePlaceHolder();

            Picasso.with(getContext()).load(source).into(new Target() {
                @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                    final BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), bitmap);

                    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());


                    result.setDrawable(drawable);
                    result.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

                    content.setText(content.getText());




                    // cache is now warmed up
                }
                @Override public void onBitmapFailed(Drawable errorDrawable) { }
                @Override public void onPrepareLoad(Drawable placeHolderDrawable) { }
            });
            return result;

}

这使用缓存,不再是需要AsyncTask的同步调用。

感谢:Fetch images with Callback in Picasso?

答案 3 :(得分:0)

使用毕加索的另一种简单方法是创建自定义TextView,并使其实现毕加索的Target接口。 然后,您可以做这样简单的事情。

        Picasso.get().load("Some_img_url").placeholder(R.drawable.ic_launcher_foreground).into(tv)

下面是课程

class TextViewWithImageLoader @JvmOverloads constructor(

context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr), Target {
enum class Direction { START, END, TOP, BOTTOM }

private var mWidthInPixels: Int = 0
private var mHeightInPixels: Int = 0
private var mDirection: Direction = Direction.START //default value

// This method initialize the required parameters for the TextView to load the image
fun setupImageLoader(widthInPixels: Int, heightInPixels: Int, direction: Direction) {
    mWidthInPixels = widthInPixels
    mHeightInPixels = heightInPixels
    mDirection = direction
}

// sets the size of the drawable
private fun setDrawableBounds(drawable: Drawable) {
    drawable.setBounds(0, 0, mWidthInPixels, mHeightInPixels)
}

// Sets the initial placeholder drawable
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
    //checking if height and width are valid
    if (placeHolderDrawable != null && mWidthInPixels > 0 && mHeightInPixels > 0) {
        setDrawableBounds(placeHolderDrawable)
        setDrawable(placeHolderDrawable)
    }
}

// set the drawable based on the Direction enum
private fun setDrawable(placeHolderDrawable: Drawable?) {
    when (mDirection) {
        Direction.START -> setCompoundDrawables(placeHolderDrawable, null, null, null);
        Direction.END -> setCompoundDrawables(null, null, placeHolderDrawable, null);
        Direction.TOP -> setCompoundDrawables(null, placeHolderDrawable, null, null);
        Direction.BOTTOM -> setCompoundDrawables(null, null, null, placeHolderDrawable);
    }
}

//In this method we receive the image from the url
override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
    //checking if height and width are valid
    if (mWidthInPixels > 0 && mHeightInPixels > 0) {
        val drawable = BitmapDrawable(resources, bitmap)
        setDrawableBounds(drawable)
        setDrawable(drawable)
    }
}

override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
    //Do nothing as we are already setting a default value in onPrepareLoad method
    // you can add your logic here if required
 }
}

您可以直接使用此类,或者,如果您当前拥有自己的自定义视图,则可以扩展此类。

您可以通过这种媒介article来了解更多详情

OR

您可以在github上看到示例项目