将 URL 中的 ImageView 加载到主屏幕小部件的 RemoteView 中

Posted

技术标签:

【中文标题】将 URL 中的 ImageView 加载到主屏幕小部件的 RemoteView 中【英文标题】:Load ImageView from URL into RemoteView of a Home Screen Widget 【发布时间】:2018-06-08 03:54:45 【问题描述】:

我正在基于 Google StackWidget 示例为我的 android 应用开发一个简单的小部件:https://android.googlesource.com/platform/development/+/master/samples/StackWidget/src/com/example/android/stackwidget/StackWidgetService.java

我正在使用 Glide 图像库并尝试在扩展 RemoteViewsServicegetViewAt 类的 getViewAt 方法上填充 ImageView。我的代码类似于:

Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(() ->
    Glide.with(context)
        .asBitmap()
        .load(widgetItems.get(position).image_url)
        .into(new SimpleTarget<Bitmap>(512, 512) 
            @Override
            public void onResourceReady(Bitmap bitmap, Transition transition) 
                rv.setImageViewBitmap(R.id.widget_item_image, bitmap);
            
        )
);

从 URL 加载图像以从 Android Widget 填充 RemoteView 的最佳方法是什么?

【问题讨论】:

不要异步执行 (onResourceReady())。当您返回RemoteViews时,它们必须完全填写。 【参考方案1】:

只需要同步进行。这似乎工作正常:

    try 
        Bitmap bitmap = Glide.with(context)
                .asBitmap()
                .load(widgetItems.get(position).image_url)
                .submit(512, 512)
                .get();

        rv.setImageViewBitmap(R.id.widget_item_image, bitmap);
     catch (Exception e) 
        e.printStackTrace();
    

【讨论】:

我的小部件非常小【参考方案2】:

Glide 有一个结构叫做:AppWidgetTarget:

在 Kotlin 中:

    val awt: AppWidgetTarget = object : AppWidgetTarget(context.applicationContext, R.id.img, remoteViews, *appWidgetIds) 
        override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) 
            super.onResourceReady(resource, transition)
        
    

    var options = RequestOptions().
            override(300, 300).placeholder(R.drawable.placeholder_img).error(R.drawable.error_img)

    Glide.with(context.applicationContext).asBitmap().load(imageUrl).apply(options).into(awt)

在 Java 中:

   AppWidgetTarget awt = new AppWidgetTarget(context, R.id.img_dog, remoteViews, appWidgetIds) 
        @Override
        public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) 
            super.onResourceReady(resource, transition);
        
    ;

    RequestOptions options = new RequestOptions().
            override(300, 300).placeholder(R.drawable.placeholder_img).error(R.drawable.error_img)


    Glide.with(context.getApplicationContext())
            .asBitmap()
            .load(imageUrl)
            .apply(options)
            .into(awt);
文档:https://futurestud.io/tutorials/glide-loading-images-into-notifications-and-appwidgets 在当前版本的 Glide 4.7.1 上测试

【讨论】:

您应该使用 applicationContext 来避免在刷新窗口小部件视图时在某些设备上出现 IllegalArgumentException 我更新了 Kotlin 答案以在 'with()' 方法中使用应用程序上下文。 Java 的答案已经在使用应用程序上下文。问候。 @dipcore 你的意思是那个异常 -> java.lang.IllegalArgumentException: RemoteViews for widget update 超出了最大位图内存使用量? 没有。这是一个不同的问题。要解决 OOM,可以使用较小的位图或在 Glide 中调整图像大小。 Glide — Image Resizing & Scaling. 未解决的参考:AppWidgetTarget【参考方案3】:

java 中的另一个例子。

  static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId) 
    String url = "https://firebasestorage.googleapis.com/v0/b/telling-299f3.appspot.com/o/POSTS%2Fcropped1099087212.jpg?alt=media&token=6a3bca19-6483-484d-a7e3-64c25a8a77a8";

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget);

    Intent intent = new Intent(context, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

    AppWidgetTarget awt = new AppWidgetTarget(context, R.id.widget_post_image, views, appWidgetId) 
        @Override
        public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) 
            super.onResourceReady(resource, transition);
        
    ;

    RequestOptions options = new RequestOptions().
            override(300, 300).placeholder(R.drawable.post_placeholder).error(R.drawable.post_placeholder);


    Glide.with(context.getApplicationContext())
            .asBitmap()
            .load(url)
            .apply(options)
            .into(awt);
    //views.setImageViewBitmap(R.id.widget_post_image, bitmap);

    views.setOnClickPendingIntent(R.id.widget_post_image, pendingIntent);

    // Instruct the widget manager to update the widget
    appWidgetManager.updateAppWidget(appWidgetId, views);

我的 app_widget.xml 文件包含

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:background="#09C"
android:padding="@dimen/widget_margin">

<ImageView
    android:id="@+id/widget_post_image"
    android:layout_
    android:layout_
    android:layout_gravity="center"
    android:src="@drawable/placeholder_image_one" />
</LinearLayout>

【讨论】:

以上是关于将 URL 中的 ImageView 加载到主屏幕小部件的 RemoteView 中的主要内容,如果未能解决你的问题,请参考以下文章

如何从 URL 将图像加载到 imageView? [复制]

如何在 Android 中通过 URL 加载 ImageView? [关闭]

如何将图像从 url 加载到小部件的 android 远程视图中

Android - 在显示进度时将图像从 URL 加载到 ImageView(不保存图像)

如何使用 Firebase 中的 Glide 仅加载部分图像?

Android:如何在不加载完整位图的情况下将流式图像即时渲染到 ImageView?