RecyclerView里面的RecyclerView在RecyclerView里面,在findViewById上抛出空指针

时间:2016-11-11 15:02:15

标签: android android-recyclerview android-cardview

我正在尝试使用RecyclerView,其中每一行都是一个CardLayout,它还包含一个RecyclerView(带有Header,Items和Footer)。我试图从OuterRecyclerView实现OnBind中的innerRecyclerView,但继续得到一个nullpointer。

“主要”活动代码:

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;

import com.squareup.timessquare.CalendarPickerView;

import java.util.List;

import ch.zhaw.it15a_zh.psit3_03.mealmanager.R;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.adapters.OuterWeekplanAdapter;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.db.repos.UserPlannedRecipesRepo;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.models.UserPlannedRecipe;

public class WeekPlanActivity extends AppCompatActivity {
  private RecyclerView outerRecyclerView;
  private CalendarPickerView calendar;
  private UserPlannedRecipesRepo uprr = new UserPlannedRecipesRepo();
  private List<UserPlannedRecipe> userPlannedRecipeList;
  private List<String> distinctUserPlannedDates;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Hide Top Toolbar form android device
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    //Set LayoutFile
    setContentView(R.layout.activity_weekplan);
    /* BEGIN TOOLBAR */
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_weekplan_overview);
    setSupportActionBar(toolbar);
    getSupportActionBar().setTitle(R.string.toolbar_title_weekplan_activity);
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    /* END TOOLBAR */

    outerRecyclerView = (RecyclerView) findViewById(R.id.activity_weekplan_outer_recyclerview);
    distinctUserPlannedDates = uprr.getDistinctListOfPlannedDates();

    OuterWeekplanAdapter outerWeekplanAdapter =
      new OuterWeekplanAdapter(getApplicationContext(), distinctUserPlannedDates);

    RecyclerView.LayoutManager manager = new LinearLayoutManager(getApplicationContext());
    outerRecyclerView.setLayoutManager(manager);
    outerRecyclerView.setItemAnimator(new DefaultItemAnimator());
    outerRecyclerView.setAdapter(outerWeekplanAdapter);

  }

  //Inflate Options Menu to show additional buttons in toolbar
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_weekplan_main_menu, menu);
    return super.onCreateOptionsMenu(menu);
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case R.id.ic_action_weekplan_add:
        Intent intent = new Intent(this, DateRangePicker.class);
        Context context = this;
        context.startActivity(intent);
    }
    return super.onOptionsItemSelected(item);
  }


}

Inner RecyclerView适配器

import android.content.Context;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.picasso.Picasso;

import java.util.List;

import ch.zhaw.it15a_zh.psit3_03.mealmanager.R;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.db.repos.RecipeRepo;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.db.repos.UserPlannedRecipesRepo;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.models.Recipe;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.models.UserPlannedRecipe;

public class InnerWeekplanAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
  private static final int TYPE_HEADER = 0;
  private static final int TYPE_ITEM = 1;
  private static final int TYPE_FOOTER = 2;
  private List<UserPlannedRecipe> userPlannedRecipeList;
  private UserPlannedRecipesRepo uprr = new UserPlannedRecipesRepo();
  private RecipeRepo recipeRepo = new RecipeRepo();
  private Context context;
  private int recipeID;

  public InnerWeekplanAdapter(List<UserPlannedRecipe> userPlannedRecipeList, Context context) {
    this.userPlannedRecipeList = userPlannedRecipeList;
    this.context = context;
  }


  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_HEADER) {
      View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_weeplan_day_header, parent, false);
      return new WeekplanHeaderViewHolder(v);
    } else if (viewType == TYPE_FOOTER) {
      View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_weekplan_day_footer, parent, false);
      return new WeekplanFooterViewHolder(v);
    } else if (viewType == TYPE_ITEM) {
      View v =
        LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_weekplan_day_planned_recipe, parent, false);
      return new WeekplanItemViewHolder(v);
    }
    return null;
  }

  @Override
  public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {


    if (holder instanceof WeekplanHeaderViewHolder) {
      WeekplanHeaderViewHolder weekplanHeaderViewHolder = (WeekplanHeaderViewHolder) holder;
      //TODO Set header fields with get repo information

      recipeID = userPlannedRecipeList.get(position).getPlannedRecipeID();
      weekplanHeaderViewHolder.textview_date_of_weekplan_row
        .setText(userPlannedRecipeList.get(position).getDatePlanned().toString());

    } else if (holder instanceof WeekplanItemViewHolder) {
      WeekplanItemViewHolder weekplanItemViewHolder = (WeekplanItemViewHolder) holder;
      Recipe recipe = new RecipeRepo().getRecipe(userPlannedRecipeList.get(position - 1).getPlannedRecipeID());

      //Sets Recipe Name
      weekplanItemViewHolder.textView_recipe_name.setText(recipe.getName());
      //Sets Image Thumbnail
      String imageID = recipe.getImage();
      imageID = imageID.substring(0, imageID.lastIndexOf("."));
      Uri uri = Uri.parse("android.resource://" + context.getPackageName() + "/drawable/" + imageID);
      Picasso.with(context).load(uri).error(R.drawable.placeholder).placeholder(R.drawable.placeholder)
        .into(weekplanItemViewHolder.imageView_thumbnail_recipe_image);
      //Sets Short Recipe Description
      weekplanItemViewHolder.textView_short_recipe_description.setText(recipe.getDescription());
      //Sets Cooking Time
      weekplanItemViewHolder.textView_cookingTime.setText(String.valueOf(recipe.getCookingTime()));
      //TODO implement RemoveRecipeFromPlanning-Button functionality

    } else {
      WeekplanFooterViewHolder weekplanFooterViewHolder = (WeekplanFooterViewHolder) holder;
      weekplanFooterViewHolder.button_plan_recipes_for_this_day.setText("Add Recipes to this day");
      //TODO implement AddRecipesToThisDay-Button functionality
    }
  }

  @Override
  public int getItemCount() {
    return userPlannedRecipeList.size() + 2;
  }

  @Override
  public int getItemViewType(int position) {
    if (isPositionHeader(position)) {
      return TYPE_HEADER;
    } else if (isPositionFooter(position)) {
      return TYPE_FOOTER;
    }
    return TYPE_ITEM;
  }

  private boolean isPositionHeader(int position) {
    return position == 0;
  }

  private boolean isPositionFooter(int position) {
    return position == userPlannedRecipeList.size() + 1;
  }


  /*BEGIN VIEWHOLDERS*/
  public class WeekplanHeaderViewHolder extends RecyclerView.ViewHolder {
    public TextView textview_date_of_weekplan_row;

    public WeekplanHeaderViewHolder(View view) {
      super(view);
      this.textview_date_of_weekplan_row = (TextView) itemView.findViewById(R.id.textview_date_of_weekplan_row);
    }
  }

  public class WeekplanItemViewHolder extends RecyclerView.ViewHolder {
    public ImageView imageView_thumbnail_recipe_image;
    public TextView textView_recipe_name;
    public TextView textView_short_recipe_description;
    public TextView textView_cookingTime;
    public ImageButton imageButton_remove_recipe_from_planning;

    public WeekplanItemViewHolder(View view) {
      super(view);
      this.imageView_thumbnail_recipe_image = (ImageView) view.findViewById(R.id.imageView_thumbnail_recipe_image);
      this.textView_recipe_name = (TextView) view.findViewById(R.id.textView_recipe_name);
      this.textView_short_recipe_description = (TextView) view.findViewById(R.id.textView_short_recipe_description);
      this.textView_cookingTime = (TextView) view.findViewById(R.id.cookingTime);
      //this.imageButton_remove_recipe_from_planning =
      //  (ImageButton) view.findViewById(R.id.imageButton_remove_recipe_from_planning);
      //Set Button functionality for removing a recipe from a recyclerview
      ImageButton button = (ImageButton) view.findViewById(R.id.imageButton_remove_recipe_from_planning);
      button.setOnClickListener(new Button.OnClickListener() {
        @Override
        public void onClick(View v) {
          Toast.makeText(context, "Item Removed", Toast.LENGTH_SHORT).show();
        }
      });
    }
  }

  public class WeekplanFooterViewHolder extends RecyclerView.ViewHolder {
    public Button button_plan_recipes_for_this_day;

    public WeekplanFooterViewHolder(View view) {
      super(view);
      this.button_plan_recipes_for_this_day = (Button) view.findViewById(R.id.button_plan_recipes_for_this_day);
    }
  }
  /*END VIEWHOLDERS*/

}

外部RecyclerView适配器

import android.content.Context;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.List;

import ch.zhaw.it15a_zh.psit3_03.mealmanager.R;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.db.repos.UserPlannedRecipesRepo;
import ch.zhaw.it15a_zh.psit3_03.mealmanager.models.UserPlannedRecipe;

public class OuterWeekplanAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
  private static Context context;
  private static OuterWeekplanAdapter outerWeekplanAdapter;
  private List<String> distinctListOfPlannedDates;
  private List<UserPlannedRecipe> userPlannedRecipeList;
  private UserPlannedRecipesRepo userPlannedRecipesRepo = new UserPlannedRecipesRepo();
  private RecyclerView innerRecyclerView;

  public OuterWeekplanAdapter(Context applicationContext, List<String> distinctListOfPlannedDates) {
    context = applicationContext;
    this.distinctListOfPlannedDates = distinctListOfPlannedDates;

  }

  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_weekplan_cardview, parent, false);
    return new OuterWeekplanViewHolder(v);
  }


  @Override
  public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

CRASH在这方面表现出色:

    innerRecyclerView = (RecyclerView) innerRecyclerView.findViewById(R.id.activity_weekplan_inner_recyclerview);
    userPlannedRecipeList =
      userPlannedRecipesRepo.getUserPlannedRecipeFromSpecificDate(distinctListOfPlannedDates.get(position));
    InnerWeekplanAdapter innerWeekplanAdapter = new InnerWeekplanAdapter(userPlannedRecipeList, context);
    RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
    innerRecyclerView.setLayoutManager(manager);
    innerRecyclerView.setItemAnimator(new DefaultItemAnimator());
    innerRecyclerView.setAdapter(innerWeekplanAdapter);

  }

  @Override
  public int getItemCount() {
    return distinctListOfPlannedDates.size();
  }

  public class OuterWeekplanViewHolder extends RecyclerView.ViewHolder {
    public OuterWeekplanViewHolder(View itemView) {
      super(itemView);
    }
  }
}

“主要”活动布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".activities.WeekPlanActivity">

  <include
      layout="@layout/toolbar_weekplan_overview"
      android:id="@+id/toolbar_weekplan_overview"/>

  <android.support.v7.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/activity_weekplan_outer_recyclerview"
      android:layout_below="@id/toolbar_weekplan_overview"
      />

</RelativeLayout>

CardView布局:          

  <android.support.v7.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/activity_weekplan_inner_recyclerview"
      />

</android.support.v7.widget.CardView>

崩溃讯息:

                                             --------- beginning of crash
11-11 15:52:07.691 6350-6350/? E/AndroidRuntime: FATAL EXCEPTION: main
                                             Process: ch.zhaw.it15a_zh.psit3_03.mealmanager, PID: 6350
                                             java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.support.v7.widget.RecyclerView.findViewById(int)' on a null object reference
                                                 at ch.zhaw.it15a_zh.psit3_03.mealmanager.adapters.OuterWeekplanAdapter.onBindViewHolder(OuterWeekplanAdapter.java:41)
                                                 at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5825)
                                                 at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5858)
                                                 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5094)
                                                 at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4970)
                                                 at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029)
                                                 at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414)
                                                 at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377)
                                                 at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)
                                                 at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3315)
                                                 at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:2843)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:716)
                                                 at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:462)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5963)
                                                 at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
                                                 at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:135)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5963)
                                                 at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
                                                 at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
                                                 at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5963)
                                                 at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5963)
                                                 at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
                                                 at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
                                                 at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5963)
                                                 at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
                                                 at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2672)
                                                 at android.view.View.measure(View.java:18850)
                                                 at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2102)
                                                 at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1218)
                                                 at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1454)
                                                 at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1109)
                                                 at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6046)
                                                 at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
                                                 at android.view.Choreographer.doCallbacks(Choreographer.java:670)
                                                 at android.view.Choreographer.doFrame(Choreographer.java:606)
                                                 at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
                                                 at android.os.Handler.handleCallback(Handler.java:739)
                                                 at android.os.Handler.dispatchMessage(Handler.java:95)
                                                 at android.os.Looper.loop(Looper.java:152)
                                                 at android.app.ActivityThread.main(ActivityThread.java:5507)
                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

2 个答案:

答案 0 :(得分:1)

您似乎正在使用错误的视图从

调用findViewById( )
 innerRecyclerView = (RecyclerView) holder.findViewById(R.id.activity_weekplan_inner_recyclerview);

而不是

 innerRecyclerView = (RecyclerView) innerRecyclerView.findViewById(R.id.activity_weekplan_inner_recyclerview);

答案 1 :(得分:1)

在外部RecyclerView适配器的OuterWeekplanViewHolder中 添加这个

innerRecyclerView = (RecyclerView)itemView.findViewById(R.id.R.id.activity_weekplan_inner_recyclerview);

然后在OnBindViewHolder中使用它,就像这样

holder.innerRecyclerView.setLayoutManager(manager);
holder.innerRecyclerView.setAdapter(adapter);