【问题标题】:no Data displayed in my Listview Widget我的 Listview 小部件中没有显示数据
【发布时间】: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_width="match_parent"
    android:layout_height="match_parent"
    android:background="#09C"
    android:padding="@dimen/widget_margin">

    <ListView
        android:id="@+id/list_view_widget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        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_width="match_parent"
    android:layout_height="match_parent"
    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_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">
    </TextView>
</LinearLayout>

谢谢。

【问题讨论】:

    标签: android listview android-widget


    【解决方案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 代码是正确的,您需要检查数据的来源,在这种情况下,我认为静态变量的值是问题的原因。让我知道这是否有帮助。祝你好运。

    【讨论】:

      猜你喜欢
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 2022-12-06
      • 1970-01-01
      • 2023-01-31
      • 2019-01-13
      • 2021-09-21
      • 1970-01-01
      相关资源
      最近更新 更多