Вывод массива данных в RecyclerView

Мне необходимо вывести массив данных в мой список RecyclerView. Создала класс CustomArrayAdapter

public class CustomArrayAdapter extends RecyclerView.Adapter<CustomArrayAdapter.ViewHolder> {
private CustomAdapterOnItemClicked customAdapterOnItemClicked;
private List<ListExampleClass> exampleListArrey = new ArrayList<>();
private Context context;

public CustomArrayAdapter(List<ListExampleClass> exampleListArrey, CustomAdapterOnItemClicked customAdapterOnItemClicked, Context context) {
    this.exampleListArrey = exampleListArrey;
    this.context = context;
    this.customAdapterOnItemClicked = customAdapterOnItemClicked;
}

@NonNull
@Override
public CustomArrayAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(context.getApplicationContext()).inflate(R.layout.example_layout, parent, false);
    return new ViewHolder(view, customAdapterOnItemClicked);
}

@Override
public void onBindViewHolder(@NonNull CustomArrayAdapter.ViewHolder holder, int position) {
    holder.setData(exampleListArrey.get(position));
}

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

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
    TextView tvCheif;
    ImageView imCheif;
    private CustomAdapterOnItemClicked customAdapterOnItemClicked;

    public ViewHolder(@NonNull View itemView, CustomAdapterOnItemClicked customAdapterOnItemClicked) {
        super(itemView);
        tvCheif = (TextView) itemView.findViewById(R.id.tvCheif);
        imCheif = (ImageView) itemView.findViewById(R.id.imChief);
        this.customAdapterOnItemClicked = customAdapterOnItemClicked;
        itemView.setOnClickListener(this);
    }
    public void setData(ListExampleClass listExampleClass)
    {
        tvCheif.setText(listExampleClass.getNameE());
        imCheif.setImageResource(listExampleClass.getImage_id());
    }
    @Override
    public void onClick(View v) {
      customAdapterOnItemClicked.onCustomAdapterItemClicked(getAdapterPosition());
    }
}
public interface CustomAdapterOnItemClicked {
    void onCustomAdapterItemClicked(int position);
}
//Функция для обновления экрана с параметрами
public void updateCustomAdapter(List<ListExampleClass> exampleList)
{
    exampleListArrey.clear();//очищаем
    exampleListArrey.addAll(exampleList);//получаем данные в него
    notifyDataSetChanged();
}
}

MainActivity

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private CustomArrayAdapter customArrayAdapter;
private CustomArrayAdapter.CustomAdapterOnItemClicked customAdapterOnItemClicked;
private String[] array;
private List<ListExampleClass> listExample;
private RecyclerView recyclerView;

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    FloatingActionButton fab = findViewById(R.id.fab);
    NavigationView nav_view = findViewById(R.id.nav_view);
    drawerLayout = findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawerLayout.addDrawerListener(toggle);
    toggle.syncState();
    nav_view.setNavigationItemSelectedListener(this);

    //Переход на новые активности
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem)
{
    int id = menuItem.getItemId();
    if(id == R.id.id_example)
{
    example();
}
 drawerLayout.closeDrawer(GravityCompat.START);
    return true;

     private void example()
{
      recyclerView = findViewById(R.id.rView);
   recyclerView.setLayoutManager(new LinearLayoutManager(this));//Указываем что бы был вертикальным по умолчанию
   array = getResources().getStringArray(R.array.category_array);//Массив с данными
   customArrayAdapter = new CustomArrayAdapter(listExample, customAdapterOnItemClicked, this);
   recyclerView.setAdapter(customArrayAdapter);
   }
  }

ListExampleClass

public class ListExampleClass {
String name;
int image_id;

public String getNameE() {
    return name;
}

public void setNameE(String name) {
    this.name = name;
}

public int getImage_id() {
    return image_id;
}

public void setImage_id(int image_id) {
    this.image_id = image_id;
}
}

Так вот в функции example() в MainActivity у меня не получается передать массив с данными. Приложение вылетает с ошибкой в логе:

Attempt to invoke interface method 'int java.util.List.size()' on a null object reference


Ответы (1 шт):

Автор решения: Andrew

Для начала вам нужно сформировать один объект класса, для этого ваш ListExampleClass должен получать данные. Создайте конструктор, например так:

ListExampleClass(String inName, Int inId){
this.name = inName;
this.id = inId;
}

Вот статья про конструкторы. Дальше вам нужно создать и заполнить массив объектами данного класса. У вас в коде фигурирует какой-то массив:

getResources().getStringArray(R.array.category_array);

так как вы не привели его в вопросе, то я могу допустить что там массив с именами (не знаю какими). Поэтому вы берете данный массив и формируете объект вашего класса в цикле. Так же я советую вместо list использовать ArrayList<ListExampleClass> он более гибкий чем List:

for(int i=0; i<array.size; i++){
listExample.add(ListExampleClass(array[i],i))
}

таким образом вы эту переменную:

private List<ListExampleClass> listExample;

можете поменять на:

private ArrayList<ListExampleClass> listExample = ArrayList();

в конструкторе адаптера:

ArrayList<ListExampleClass> exampleListArrey

и переменная самого адаптера:

private ArrayList<ListExampleClass> exampleListArrey = new ArrayList<>();

так же я бы вам посоветовал добавить проверку на размер массива перед передачей в адаптер. Эту проверку можно сделать в цикле или за его пределами:

for(int i=0; i<array.size; i++){
listExample.add(ListExampleClass(array[i],i));
if(listExample.size==array.size){
customArrayAdapter = new CustomArrayAdapter(listExample, customAdapterOnItemClicked, this);
recyclerView.setAdapter(customArrayAdapter);

break;
}
}

так же я вам посоветую добавить свойство задающее фиксированный размер элементов списка:

recyclerView.setHasFixedSize(true)

Вот тут есть интересная информация касательно данного свойства. Вот интересная статья по работе с списком и его адаптером которая должна вам помочь в решении данного вопроса. И туториал который полностью похож на вашу задачу, только класс немного другой.

→ Ссылка