Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

684
01 января 2017, 17:56

Обучался вот по этому Уроку, и по нему все работает. Проблема в следующем: мне надо сделать тоже самое, но с применением фрагментов. Разметку и код Адаптера я оставил такие же, а из главного Активити перенес код в класс наследующий Fragment. У меня это выглядит так:

import android.content.Context;     
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
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.ArrayList;
import java.util.List;
public class TestClass extends Fragment{
private RecyclerView recyclerView;
private MyAdapter adapter;
private List<RecyclerItem> listItems;
private Context context;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View x =  inflater.inflate(R.layout.test_layout,null);
    recyclerView = (RecyclerView) x.findViewById(R.id.recyclerView);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(context));
    listItems = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        listItems.add(new RecyclerItem("Item " + (i + 1), ""+ i + 1 );
    }
    adapter = new MyAdapter(listItems, context);
    recyclerView.setAdapter(adapter);
    return x;
}}

Все отображает нормально, но при нажатии на меню выбивает ошибку в Адаптере

Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

в этой строке:

PopupMenu popupMenu = new PopupMenu(context, holder.txtOptionDigit);

Полный код Адаптера:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private List<RecyclerItem> listItems;
private Context context;
public RecyclerAdapter(List<RecyclerItem> listItems, Context context) {
    this.listItems = listItems;
    this.context = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
    return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    final RecyclerItem itemList = listItems.get(position);
    holder.txtTitle.setText(itemList.getTitle());
    holder.txtDescription.setText(itemList.getDescription());
    holder.txtOptionDigit.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            PopupMenu popupMenu = new PopupMenu(context, holder.txtOptionDigit);
            popupMenu.inflate(R.menu.option_menu);
            popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    switch (item.getItemId()) {
                        case R.id.mnu_item_save:
                            break;
                        case R.id.mnu_item_delete:    
                            listItems.remove(position);
                            notifyDataSetChanged();
                            break;
                        default:
                            break;
                    }
                    return false;
                }
            });
            popupMenu.show();
        }
    });
}
@Override
public int getItemCount() {
    return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
    public TextView txtTitle;
    public TextView txtDescription;
    public TextView txtOptionDigit;
    public ViewHolder(View itemView) {
        super(itemView);
        txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
        txtDescription = (TextView) itemView.findViewById(R.id.txtDescription);
        txtOptionDigit = (TextView) itemView.findViewById(R.id.txtOptionDigit);
    }
}}

Подскажите, пожалуйста, в чем тут дело.

Answer 1

У вас не инициализирована переменная context, которую вы передаёте в адаптер. А её в адаптер вообще, в общем-то, передавать и не надо. Вы можете получить контекст из любой View, которая есть в холдере. Т.е. вам надо:

  1. Удалить переменную Context context из фрагмента.
  2. Удалить переменную Context context из адаптера.
  3. Удалить аргумент Context context из конструктора адаптера.
  4. Удалить передачу удалённой переменной context из аргумента адаптера при его создании во фрагменте
  5. Создать переменную Context context в onBindViewholder методе адаптера.
  6. Инициализировать её контекстом, взятым из View, которая есть в холдере так:
context = holder.itemView.getContext();

И почитайте что такое NPE тут: Что такое Null Pointer Exception и как его исправить?

READ ALSO
Как называется такой стиль дизайна? [требует правки]

Как называется такой стиль дизайна? [требует правки]

Хочу сделать сайт на руби он рэилс и хотел главную страницу сделать в стиле как тут http://anwarim/appdash/ Как называется такой стил дизайна *? Я хочу...

355
Как сохранять данные на андроиде [требует правки]

Как сохранять данные на андроиде [требует правки]

Нашел програму которая превращает сайт в программу андроидБереш сайт, переделываеш под размеры для телефона и закидываеш в програму

431
Как загрузить новый уровень в Unity 5.3+?

Как загрузить новый уровень в Unity 5.3+?

До версии 53 я мог спокойно написать:

549
Telegram Bot c# CallbackQuery

Telegram Bot c# CallbackQuery

Здравствуйте! Уже успел сломать голову с TelegramBot

2229