通过意图将数据从应用程序传递到小部件时,空指针

时间:2018-08-03 16:49:49

标签: java android android-recyclerview widget

我有一份使用翻新程序检索的食谱列表。然后,我获得配方名称,并且想要更新与我的应用程序关联的小部件以显示所选的recipeNamerecipeName反映在我的RecyclerView的适配器中。

当用户单击RecylcerView中的某个项目时,我想更新该应用程序所具有的关联小部件。

下面是RecyclerView的适配器,在这里我有.setOnClickListener()方法,并通过Intent传递我的所有数据。

        @Override
public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, final int position) {
        String id = mRecipeDataSet.get(position).getId();
        //The recipe name I want to pass to my widget
        final String recipeName = mRecipeDataSet.get(position).getName();
        holder.mTextView.setText(id);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(con, BakingWidgetProvider.class);
                intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
                int[] ids = AppWidgetManager.getInstance(con).getAppWidgetIds(new ComponentName(con, BakingWidgetProvider.class));
                if(ids != null && ids.length > 0) {
                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
                    intent.putExtra(RECIPE_NAME, recipeName);
                    con.sendBroadcast(intent);
                }
                Intent i = new Intent(con, IndividualRecipeActivity.class);
                Bundle bundle = new Bundle();
                bundle.putParcelableArrayList("Recipe_List", (ArrayList<? extends Parcelable>) mRecipeDataSet);
                i.putExtras(bundle);
                i.putExtra("Position",position);
                con.startActivity(i);
            }
        });

}

下面是管理我的窗口小部件的BakingWidgetProvider类。每当用户从RecyclerView单击新项目时,我都希望更新窗口小部件界面:

公共类BakingWidgetProvider扩展了AppWidgetProvider {

private static final String RECIPE_NAME = "RECIPE_NAME";
public static final String ACTION_TEXT_CHANGED = "kitchenpal.troychuinard.com.kitchenpal.TEXT_CHANGED";
private static String mRecipeName;

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId) {

    CharSequence widgetText = context.getString(R.string.appwidget_text);
    // Construct the RemoteViews object
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.baking_widget_provider);
    Log.v("WIDGET", mRecipeName);
    views.setTextViewText(R.id.selected_recipe, mRecipeName);
    Intent intent = new Intent(context, MainActivity.class);
    PendingIntent pIntent = PendingIntent.getActivity(context, 0, 
     intent, 0);
    //TODO: Why isn't my widget launching my MainActivity onClick?
    //TODO: I am trying to add a ListView of ingredients to my Widget 
     but have no idea where to begin
    views.setOnClickPendingIntent(R.id.chef, pIntent);

}

@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) {
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

@Override
public void onEnabled(Context context) {
    // Enter relevant functionality for when the first widget is created
}

@Override
public void onDisabled(Context context) {
    // Enter relevant functionality for when the last widget is disabled
}

//TODO: I cannot pass data from MyAdapter to the BakingWidgerProvider. I am simply trying to display the most recently
//TODO: selected recipe on the widget. I have scoured StackOverflow to no avail
@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(ACTION_TEXT_CHANGED)) {
        // handle intent here
        mRecipeName = intent.getStringExtra(RECIPE_NAME);
    }
    super.onReceive(context, intent);

     //        if(intent.getAction().equals("UPDATE_ACTION")) {
     //            mRecipeName = intent.getStringExtra(RECIPE_NAME);
     //            int[] appWidgetIds = 


   intent.getExtras().getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
     //            if (appWidgetIds != null && appWidgetIds.length > 0) 
     {
     //                this.onUpdate(context, 
     AppWidgetManager.getInstance(context), appWidgetIds);
     //            }
     //        } else {
     //            super.onReceive(context, intent);
     //        }
     //    }
        }
      }

更新:我已经包括了用于包含.onReceive()的替代代码,并且在此替代方法中设置了该字段。我尝试使用它来更新.onUpdateAppWidget()中的界面,但是该小部件未基于mRecipeName字段更新TextView,因为mRecipeName字段为空。

2 个答案:

答案 0 :(得分:1)

您应该在AppWidgetClass中重写onReceive。这样会收到已广播的意图,因此您可以从中检索数据

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    //Insert code here
}

然后继续添加代码以从Intent接收/分配数据。

答案 1 :(得分:1)

通过将广播发送到窗口小部件(类固醇上的BroadcastReceiver)来触发窗口小部件后,便从捆绑软件中设置了一个字段mRecipeName,但是在设置字段mRecipeName之前,您要更新RemoteView(因此mRecipeName目前为空)。做这样的事情:

@Override
public void onReceive(Context context, Intent intent) {
   mRecipeName = intent.getStringExtra(RECIPE_NAME);
   super.onReceive(context, intent);
}

实际上,使其更清洁用于生产。做类似的事情:

Intent intent = new Intent(con, BakingWidgetProvider.class);
intent.setAction("UPDATE_ACTION");
int[] ids = AppWidgetManager.getInstance(con).getAppWidgetIds(new ComponentName(con, BakingWidgetProvider.class));
if(ids != null && ids.length > 0) {
      intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
      intent.putExtra(RECIPE_NAME, recipeName);
      con.sendBroadcast(intent);
}

您的onReceive将像这样:

@Override
public void onReceive(Context context, Intent intent) {
   if(intent.getAction().equals("UPDATE_ACTION") {
       mRecipeName = intent.getStringExtra(RECIPE_NAME);
       int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
       if (appWidgetIds != null && appWidgetIds.length > 0) {
            this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
       }
   } else {
      super.onReceive(context, intent);
   }
}