带有集合(ListView)的Android小部件不显示项目
Posted
技术标签:
【中文标题】带有集合(ListView)的Android小部件不显示项目【英文标题】:Android Widget with collection (ListView) not displaying items 【发布时间】:2021-04-23 00:37:52 【问题描述】:我正在尝试为我的应用程序做一个简单的小部件,它使用 ListView 在小部件上显示来自 API 的数据,但即使日志显示数据已成功下载,列表也是空的。 显示空白列表视图,其中没有数据。没有显示错误。是什么原因造成的?
我在尝试解决此问题时使用的资源:
官方文档-https://developer.android.com/guide/topics/appwidgets#collections
类似问题 - How to use listview in a widget?
我的 AppWidgetProvider
public class Widget extends AppWidgetProvider
RemoteViews views;
void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId)
CharSequence widgetText = context.getString(R.string.appwidget_text);
// Construct the RemoteViews object
views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds)
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.my_widget);
Intent intent = new Intent(context, WidgetService.class);
remoteViews.setRemoteAdapter(R.id.appwidget_list_view, intent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
WidgetFactory 和 WidgetService
public class WidgetFactory implements RemoteViewsService.RemoteViewsFactory
final Context context;
List<SimpleCoin> list;
List<Coin> coinList;
public WidgetFactory(Context context, Intent intent)
this.context = context;
@Override
public void onCreate()
//get data from database
CoinDatabase coinDatabase = CoinDatabase.buildDatabase(context);
list = coinDatabase.coinDao().getAllSimpleCoinsNonLive();
coinList = new ArrayList<>();
@Override
public void onDataSetChanged()
//based on data from database download content (JSON)
if(list != null)
Log.d("Widget", "Coin size -> " + list.size());
StringBuilder id = new StringBuilder("id=" + list.get(0).getId());
for (int j = 0; j < list.size(); j++)
id.append(",");
id.append(list.get(j).getId());
String finalUrl = URL + id.toString() + API_KEY;
Observable.fromCallable(() ->
HttpURLConnection connection = null;
BufferedReader reader = null;
java.net.URL url1 = new URL(finalUrl);
connection = (HttpURLConnection) url1.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder buffer = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null)
buffer.append(line).append("\n");
connection.disconnect();
reader.close();
return buffer.toString();
).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<String>()
@Override
public void onSubscribe(@NonNull Disposable d)
@Override
public void onNext(@NonNull String s)
if (s != null)
try
//Create new coin and update list of coins
JSONObject object = new JSONObject(s);
for (int i = 0; i < list.size(); i++)
JSONObject jsonObject = object.getJSONObject("data").getJSONObject(String.valueOf(list.get(i).getId()));
Log.d("Widget", "Coin -> " + jsonObject.getString("name") + jsonObject.getJSONObject("quote").getJSONObject("USD").getDouble("price") + jsonObject.getJSONObject("quote").getJSONObject("USD").getDouble("percent_change_7d"));
Coin coin = new Coin(jsonObject.getString("name"), jsonObject.getJSONObject("quote").getJSONObject("USD").getDouble("price"), jsonObject.getJSONObject("quote").getJSONObject("USD").getDouble("percent_change_7d"), false);
coinList.add(coin);
getViewAt(i);
catch (JSONException e)
Log.d("Widget", "Coin -> " + e.toString());
e.printStackTrace();
@Override
public void onError(@NonNull Throwable e)
@Override
public void onComplete()
);
@Override
public void onDestroy()
@Override
public int getCount()
return list.size();
@Override
public RemoteViews getViewAt(int i)
//Set ListData based on coinList
Log.d("Widget", "Coin size getViewAt -> " + list.size() + "item num ->" + i);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.my_widget_list_item);
if(coinList != null)
if(coinList.size() > i)
Log.d("Widget", "Coin position added" + coinList.get(i).getName());
remoteViews.setTextViewText(R.id.widgetItemTaskNameLabel, coinList.get(i).getName());
return remoteViews;
@Override
public RemoteViews getLoadingView()
return null;
@Override
public int getViewTypeCount()
return 1;
@Override
public long getItemId(int i)
return i;
@Override
public boolean hasStableIds()
return true;
public class WidgetService extends RemoteViewsService
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent)
return new WidgetFactory(this.getApplicationContext(), intent);
这是我的日志:
D/Widget: Coin size getViewAt -> 1 item num ->0
D/Widget: Coin size getViewAt -> 1 item num ->0
D/Widget: Coin -> testCoin0.00.0
D/Widget: Coin size getViewAt -> 1 item num ->0
D/Widget: Coin position added testCoin
my_widget.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/colorPrimary"
android:padding="@dimen/widget_margin">
<TextView
android:id="@+id/appwidget_text"
android:layout_
android:layout_
android:layout_centerVertical="true"
android:layout_margin="8dp"
android:background="@color/colorPrimary"
android:contentDescription="@string/appwidget_text"
android:text="@string/appwidget_text"
android:textColor="#ffffff"
android:textSize="24sp"
android:textStyle="bold|italic" />
<ListView
android:id="@+id/appwidget_list_view"
android:layout_
android:layout_margin="8dp"
tools:listitem="@layout/my_widget_list_item"
android:layout_
android:background="@color/colorAccent"
android:layout_below="@id/appwidget_text">
</ListView>
</RelativeLayout>
my_widget_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_
android:paddingLeft="@dimen/widget_listview_padding_x"
android:paddingRight="@dimen/widget_listview_padding_x"
android:paddingStart="@dimen/widget_listview_padding_x"
android:paddingEnd="@dimen/widget_listview_padding_x"
android:minHeight="@dimen/widget_listview_item_height"
android:weightSum="2"
android:layout_>
<TextView
android:id="@+id/widgetItemTaskNameLabel"
android:layout_
android:gravity="start"
android:layout_weight="1"
android:textColor="@color/colorPrimary"
android:layout_gravity="center_vertical"
android:layout_ />
</LinearLayout>
【问题讨论】:
【参考方案1】:我发现了我的错误,结果证明我的 API 调用不应该是异步的,因为正如文档所述:
public void onDataSetChanged() -> 你可以在这里同步地做起重。例如,如果你需要处理一张图片,从网络中取一些东西等等,这里就可以了,同步的。在此处完成工作时,小部件将保持其当前状态,因此您无需担心锁定小部件。
所以从异步调用中获取我的数据是没有显示数据的原因
【讨论】:
以上是关于带有集合(ListView)的Android小部件不显示项目的主要内容,如果未能解决你的问题,请参考以下文章
带有 ListView 的 Android 可点击小部件在 ListItems 上不可点击
带有 ListView 的小部件为找到的每个项目显示“正在加载”