我的 Listview 小部件中没有显示数据
Posted
技术标签:
【中文标题】我的 Listview 小部件中没有显示数据【英文标题】:no Data displayed in my Listview Widget 【发布时间】:2018-11-26 16:15:56 【问题描述】:我想创建一个ListView
小部件,在小部件中显示ArrayList
的数据......
我花了很长时间尝试将ListView
添加到小部件,但它添加时没有显示任何数据。
虽然当我添加断点时我的数据在类之间成功获取
不知道是什么问题……
这些是我的课程:
第一类(BakingAppWidgetProvider):
package com.example.android.advancebakingapp.Widget;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.example.android.advancebakingapp.BuildConfig;
import com.example.android.advancebakingapp.MainActivity;
import com.example.android.advancebakingapp.Model.Ingredient;
import com.example.android.advancebakingapp.R;
import java.lang.reflect.Array;
import java.util.ArrayList;
/**
* Implementation of App Widget functionality.
*/
public class BakingAppWidgetProvider extends AppWidgetProvider
public static Ingredient[] mIngredients;
public ArrayList<Ingredient> parcelables;
public static ArrayList<Ingredient> ingredients1= new ArrayList<>();
public static final String WIDGET_UPDATE_ACTION = "android.appwidget.action.APPWIDGET_UPDATE";
private static final String TAG = "WidgetProvider";
public BakingAppWidgetProvider()
@Override
public void onReceive(final Context context, final Intent intent)
super.onReceive(context, intent);
final Bundle bundle = intent.getBundleExtra("BUNDLE");
if(bundle != null)
parcelables = (ArrayList<Ingredient>) bundle.getSerializable("INGREDIENTS");
ingredients1.addAll(parcelables);
else
Toast.makeText(context,"nuuuuuuuul",Toast.LENGTH_LONG).show();
intent.setAction(WIDGET_UPDATE_ACTION);
if (BakingAppWidgetProvider.WIDGET_UPDATE_ACTION.equals(intent.getAction()))
if (BuildConfig.DEBUG)
Log.d(BakingAppWidgetProvider.TAG, "onReceive "
+ BakingAppWidgetProvider.WIDGET_UPDATE_ACTION);
final AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
final ComponentName thisAppWidget = new ComponentName(
context.getPackageName(), BakingAppWidgetProvider.class.getName());
final int[] appWidgetIds = appWidgetManager
.getAppWidgetIds(thisAppWidget);
onUpdate(context, appWidgetManager, appWidgetIds);
/**
* method will update the ListView each time the user opens the IngredientsActivity,
* meaning that the widget will always show the last IngredientsActivity Ingredients[] that the user seen.
* @param context app context
* @param appWidgetManager app WidgetManger
* @param appWidgetIds ids which will be updated
* @param ingredients the ingredients that will fill the ListView
*
*/
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetIds[], Ingredient[] ingredients)
mIngredients = ingredients;
for (int appWidgetId : appWidgetIds)
Intent intent = new Intent(context, listViewsService.class);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.baking_app_widget_provider);
views.setRemoteAdapter(R.id.list_view_widget, intent);
ComponentName component = new ComponentName(context, BakingAppWidgetProvider.class);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view_widget);
appWidgetManager.updateAppWidget(component, views);
/**
* the widget will update itself each time the IngredientsActivity will open,meaning that this method
* is unnecessary in our implementation.
* @param context app context
* @param appWidgetManager the application WidgetManager
* @param appWidgetIds ids which will be updated
*/
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
if (BuildConfig.DEBUG)
Log.d(BakingAppWidgetProvider.TAG, "onUpdate");
Intent serviceIntent = new Intent(context,WidgetUpdateService.class);
Bundle args1 = new Bundle();
args1.putSerializable("INGREDIENTS",parcelables);
serviceIntent.putExtra("BUNDLE", args1);
context.sendBroadcast(serviceIntent);
serviceIntent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
context.startService(serviceIntent);
@Override
public void onEnabled(Context context)
@Override
public void onDisabled(Context context)
第二类(WidgetUpdateService):
package com.example.android.advancebakingapp.Widget;
import android.app.IntentService;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.widget.Toast;
import com.example.android.advancebakingapp.MainActivity;
import com.example.android.advancebakingapp.Model.Ingredient;
import com.example.android.advancebakingapp.Model.Step;
import java.util.ArrayList;
public class WidgetUpdateService extends IntentService
public static final String WIDGET_UPDATE_ACTION = "android.appwidget.action.APPWIDGET_UPDATE";
private Ingredient[]mIngredients;
ArrayList<Ingredient> parcelable = new ArrayList<>();
public WidgetUpdateService()
super("WidgetUpdateService");
@Override
protected void onHandleIntent( Intent intent)
if (intent != null && intent.getAction().equals(WIDGET_UPDATE_ACTION))
final Bundle bundle = intent.getBundleExtra("BUNDLE");
parcelable =(ArrayList<Ingredient>) bundle.getSerializable("INGREDIENTS");
if (parcelable != null)
mIngredients = new Ingredient[parcelable.size()];
for (int i = 0; i < parcelable.size(); i++)
mIngredients[i] = (Ingredient) parcelable.get(i);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(this, BakingAppWidgetProvider.class));
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
BakingAppWidgetProvider.updateAppWidget(this, appWidgetManager, appWidgetIds,mIngredients);
第三类(listViewsService):
package com.example.android.advancebakingapp.Widget;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
import android.widget.Toast;
import com.example.android.advancebakingapp.Model.Ingredient;
import com.example.android.advancebakingapp.R;
public class listViewsService extends RemoteViewsService
public static final String TAG = "ListViewsService";
/**
* @param intent intent that triggered this service
* @return new ListViewsFactory Object with the appropriate implementation
*/
public ListViewsFactory onGetViewFactory(Intent intent)
return new ListViewsFactory(this.getApplicationContext());
class ListViewsFactory implements RemoteViewsService.RemoteViewsFactory
private Context mContext;
private Ingredient[] mIngredients;
public ListViewsFactory(Context mContext)
this.mContext = mContext;
@Override
public void onCreate()
mIngredients = BakingAppWidgetProvider.mIngredients;
//Very Important,this is the place where the data is being changed each time by the adapter.
@Override
public void onDataSetChanged()
mIngredients = BakingAppWidgetProvider.mIngredients;
@Override
public void onDestroy()
@Override
public int getCount()
if (mIngredients == null)
return 0;
return mIngredients.length;
/**
* @param position position of current view in the ListView
* @return a new RemoteViews object that will be one of many in the ListView
*/
@Override
public RemoteViews getViewAt(int position)
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.baking_app_widget_ingrediant);
views.setTextViewText(R.id.text_view_recipe_widget, mIngredients[position].getIngredient());
return views;
@Override
public RemoteViews getLoadingView()
return null;
@Override
public int getViewTypeCount()
return 1;
@Override
public long getItemId(int position)
return position;
@Override
public boolean hasStableIds()
return true;
这些是我的布局:
baking_app_widget_provider.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:background="#09C"
android:padding="@dimen/widget_margin">
<ListView
android:id="@+id/list_view_widget"
android:layout_
android:layout_
android:layout_marginTop="@dimen/widgetBodyMarginTop" />
</RelativeLayout>
baking_app_widget_ingrediant.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_
android:padding="@dimen/widgetPadding"
android:background="#FFFFFF">
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/TextAppearance.AppCompat.Display1"
android:id="@+id/text_view_recipe_widget"
android:layout_
android:layout_
android:gravity="center">
</TextView>
</LinearLayout>
谢谢。
【问题讨论】:
【参考方案1】:您是否检查过是否调用了 onDataSetChanged()? 您是否在清单中声明了具有以下权限的 RemoteViews 服务?
android:permission="android.permission.BIND_REMOTEVIEWS"
【讨论】:
是的,我添加了权限:服务:android:name=".Widget.listViewsService" 并且成功调用了onDataSetChanged,但是该方法中(mIngredients)的数据为空:mIngredients = BakingAppWidgetProvider。 m成分【参考方案2】:我的建议是在这种情况下不要使用静态变量:
mIngredients = BakingAppWidgetProvider.mIngredients;
我所做的是使用意图 putExtra 方法将数据传递给远程适配器,然后从我的 listViewsService 中的意图中提取数据。使用一些虚拟数据测试您的 listViewsService 代码并验证它是否显示在小部件中。如果您可以看到虚拟数据,那么您的 listViewsService 代码是正确的,您需要检查数据的来源,在这种情况下,我认为静态变量的值是问题的原因。让我知道这是否有帮助。祝你好运。
【讨论】:
以上是关于我的 Listview 小部件中没有显示数据的主要内容,如果未能解决你的问题,请参考以下文章
我的 ListView 构建器的 ListTile 小部件不可滚动并且显示渲染问题
带有 ListView 的 Android 可点击小部件在 ListItems 上不可点击
如何在app小部件中使用ListView并在android中填充数据?