【问题标题】:Android Widget with collection (ListView) not displaying items带有集合(ListView)的Android小部件不显示项目
【发布时间】: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_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>

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_width="match_parent"
    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_height="wrap_content">

    <TextView
        android:id="@+id/widgetItemTaskNameLabel"
        android:layout_width="0dp"
        android:gravity="start"
        android:layout_weight="1"
        android:textColor="@color/colorPrimary"
        android:layout_gravity="center_vertical"
        android:layout_height="wrap_content" />

</LinearLayout>

【问题讨论】:

    标签: java android android-listview widget


    【解决方案1】:

    我发现了我的错误,结果证明我的 API 调用不应该是异步的,因为正如文档所述:

    public void onDataSetChanged() -> 你可以在这里同步地做起重。例如,如果你需要处理一张图片,从网络中取一些东西等等,这里就可以了,同步的。在此处完成工作时,小部件将保持其当前状态,因此您无需担心锁定小部件。

    所以从异步调用中获取我的数据是没有显示数据的原因

    【讨论】:

      猜你喜欢
      • 2017-05-09
      • 2017-06-09
      • 2014-04-11
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多