【问题标题】:Best way to load a notification image? [closed]加载通知图像的最佳方式? [关闭]
【发布时间】:2017-08-16 19:00:00
【问题描述】:

加载通知图片的最佳方式是什么?

这是我目前的方式:您可以看到图像同步加载,因此通知可能会延迟。这是一种不好的方式。

public Bitmap getBitmapFromURL(String strURL) {
    try {
        URL url = new URL(strURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

Bitmap bitmap = getBitmapFromURL("https://graph.facebook.com/YOUR_USER_ID/picture?type=large");

// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
builder.setLargeIcon(bitmap);
builder.setContentIntent(pendingIntent);

我真的需要一个答案才能继续我的项目。

【问题讨论】:

  • Stack Overflow 不是编程竞赛。我们要求问题有一个具体的、可验证的答案。要求“最好的”是行不通的。您需要精确缩小“最佳”的含义。你有什么要求?你有什么限制?描述您正在寻找的解决方案,然后有人可以提供它。

标签: java android push-notification


【解决方案1】:

您应该首先通知您的通知,没有图像或占位符,然后使用 AsyncTask 加载您的位图,或使用 Picasso 和 Target 回调。

将您用于第一次通知的构建器分配给您的任务,当加载位图时,将其添加到构建器,然后重新通知您的通知。

如果在完成图像加载之前内容存在更改的风险,请存储一个变量来标识要显示的当前内容,您可以在重新通知之前检查该变量。

您可以按照 google UniversalMusicPlayer 项目提供的 MediaNotificationManager 示例进行操作。

在你的情况下:

// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
//builder.setLargeIcon(bitmap); // replace this line with place holder drawable from resources
builder.setContentIntent(pendingIntent);

manager.notify(NOTIFICATION_ID, builder.build());

currentLoadImageTask = new LoadImageTask(manager, builder);
currentLoadImageTask.execute("https://graph.facebook.com/YOUR_USER_ID/picture?type=large");

// ...

static class LoadImageTask extends AsyncTask<String, Void, Bitmap> {

    final NotificationManager manager;
    final NotificationCompat.Builder builder;

    public LoadImageTask(final NotificationManager manager, final NotificationCompat.Builder builder) {
        this.manager = manager;
        this.builder = builder;
    }

    @Override
    protected Bitmap doInBackground(final String... strings) {
        if (strings == null || strings.length == 0) {
            return null;
        }
        try {
            final URL url = new URL(strings[0]);
            final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            final InputStream input = connection.getInputStream();
            return BitmapFactory.decodeStream(input);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected void onPostExecute(final Bitmap bitmap) {
        if (bitmap == null || manager == null || builder == null) {
            return;
        }
        builder.setLargeIcon(bitmap);
        manager.notify(NOTIFICATION_ID, builder.build());
    }
}

毕加索:

// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
//builder.setLargeIcon(bitmap); // replace this line with place holder drawable from resources
builder.setContentIntent(pendingIntent);

manager.notify(NOTIFICATION_ID, builder.build());

// ...

Picasso.with(context)
    .load("https://graph.facebook.com/YOUR_USER_ID/picture?type=large")
    .resize(250, 250)
    .into(new Target() {
        @Override
        public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
            builder.setLargeIcon(bitmap);
            manager.notify(NOTIFICATION_ID, builder.build());
        }

        @Override
        public void onBitmapFailed(final Drawable errorDrawable) {
             // Do nothing
        }

        @Override
        public void onPrepareLoad(final Drawable placeHolderDrawable) {
             // Do nothing
        }
    });

如果不在 UiThread 中你可以创建一个 Runnable 并在 Looper 中执行它

 final Handler uiHandler = new Handler(Looper.getMainLooper());
 uiHandler.post(new Runnable() {
      @Override
      public void run() {
           // Call from here
      }
 });

Picasso 更好,仅仅是因为使用了缓存。

我强烈建议您调整您在通知中设置的每个位图的大小,因为如果您不这样做,它很容易引发 OutOfMemoryException。

【讨论】:

  • 这是我一直在寻找的答案。但是,您确定这是使用毕加索的正确方法吗?
  • 这不是您通过 into() 方法直接引用您的 imageView 的“经典”方式,但在您的情况下,您必须获取加载的位图结果,因为通知管理器不允许您访问 imageview .使用 Target 是您可以通过 picasso 获得异步位图加载结果的方法。 square.github.io/picasso/2.x/picasso/com/squareup/picasso/…
  • 我在这一行收到错误java.lang.IllegalStateException: Method call should happen from the main thread. .into(new Target() {
  • 是的,它必须,或者你可以指定一个执行者。
  • 我该如何解决这个错误?
【解决方案2】:

请记住,如果您使用网络加载某些内容,则必须稍等片刻。 有几种解决方案:

  1. 像您的示例一样从网络加载图像并显示。

  2. 通过更新通知显示存根图像并稍后显示下载的图像

  3. 使用一点有助于缓存网页英寸。例如,毕加索

http://square.github.io/picasso/

【讨论】:

    【解决方案3】:

    使用Picasso lib 从 url 加载图像

     Picasso.with(this.load(imageUri).into(imageview_id);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-08
      • 2011-09-03
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多