问题描述
我正在尝试为我的应用程序做一个简单的小部件,它使用 ListView 在小部件上显示来自 API 的数据,但即使日志显示数据已成功下载,该列表也是空的。 显示空白列表视图,其中没有数据。没有错误显示。是什么原因造成的?
我在尝试解决此问题时使用的资源:
官方文档 - https://developer.android.com/guide/topics/appwidgets#collections
类似问题 - How to use listview in a widget?
void printIntArray( int rows,int cols,int array[ rows ][ cols ] )
{
for ( int ii = 0; ii < rows; ii++ )
{
for ( int jj = 0; jj < cols; jj++ )
{
printf( "%d ",array[ ii ][ jj ] );
}
printf( "\n" );
}
}
WidgetFactory 和 WidgetService
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,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);
}
}
这是我的日志:
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);
}
}
my_widget.xml
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_list_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/colorPrimary"
android:padding="@dimen/widget_margin">
<TextView
android:id="@+id/appwidget_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_margin="8dp"
tools:listitem="@layout/my_widget_list_item"
android:layout_height="wrap_content"
android:background="@color/colorAccent"
android:layout_below="@id/appwidget_text">
</ListView>
</RelativeLayout>
解决方法
我发现了我的错误,结果我的 API 调用不应该是异步的,因为正如文档所说:
public void onDataSetChanged() -> 您可以在这里同步进行举升。例如,如果您需要处理图像,从网络中获取某些内容等,可以在此处同步进行。小部件将在此处完成工作时保持其当前状态,因此您无需担心小部件被锁定。
所以从异步调用中获取我的数据是数据没有显示的原因