没有数据显示在我的Listview小部件中

时间:2018-06-17 17:28:47

标签: android listview android-widget

我想创建一个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)
    { }




}
&#13;
&#13;
&#13;

第二个类(WidgetUpdateService):

&#13;
&#13;
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);
       }
    }
}
&#13;
&#13;
&#13;

第三个类(listViewsService):

&#13;
&#13;
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;
    }
}
&#13;
&#13;
&#13;

这些是我的布局:

baking_app_widget_provider.xml:

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

baking_app_widget_ingrediant.xml:

&#13;
&#13;
<?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>
&#13;
&#13;
&#13;

谢谢。

2 个答案:

答案 0 :(得分:0)

你检查过onDataSetChanged()是否被调用? 您是否使用以下权限在清单中声明了RemoteViews服务?

android:permission =“android.permission.BIND_REMOTEVIEWS”

答案 1 :(得分:0)

我的建议是不使用像这种情况那样的静态变量:

mIngredients = BakingAppWidgetProvider.mIngredients;

我所做的是使用intent putExtra方法将数据传递到远程适配器,然后从listViewsService中的intent中提取数据。使用一些虚拟数据测试listViewsService代码,并验证它是否显示在窗口小部件中。如果你可以看到虚拟数据,那么你的listViewsService代码是正确的,你需要检查数据的来源,在这种情况下,我认为静态变量的值是问题的原因。如果这有帮助,请告诉我。祝你好运。