У меня есть вложенный recyclerview, и я хочу динамически добавлять подэлементы в отдельные элементы, а также иметь возможность добавлять элементы. Я могу добавлять элементы, но когда я добавляю подэлементы, программа просто перестает работать. Я не уверен, как у меня может быть каждый элемент с уникальным количеством подэлементов.
Код ошибки, когда я нажимаю добавить подэлемент
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.recycledviewpooltest, PID: 14770
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.recycledviewpooltest.SubItemAdapter.addExercise(com.example.recycledviewpooltest.SubItem)' on a null object reference
at com.example.recycledviewpooltest.ItemAdapter$ItemViewHolder$1.onClick(ItemAdapter.java:81)
at android.view.View.performClick(View.java:5610)
at android.view.View$PerformClick.run(View.java:22265)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Подпункт
import android.widget.Spinner;
public class SubItem {
private String mWorkoutName;
private String workoutNum;
private String munit;
private Spinner mUnitSpinner;
public SubItem(String workoutName, String num, String unit) {
mWorkoutName = workoutName;
workoutNum = num;
munit = unit;
}
public Spinner getmUnitSpinner() {
return mUnitSpinner;
}
public void setSpinner (Spinner _mUnitSpinner) {
mUnitSpinner = _mUnitSpinner;
}
public String getmWorkoutName() {
return mWorkoutName;
}
public String getWorkoutNum() {
return workoutNum;
}
public String getMunit() {
return munit;
}
public void setmWorkoutName(String mWorkoutName) {
this.mWorkoutName = mWorkoutName;
}
public void setWorkoutNum(String workoutNum) {
this.workoutNum = workoutNum;
}
public void setMunit(String munit) {
this.munit = munit;
}
}
адаптер подэлемента
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class SubItemAdapter extends RecyclerView.Adapter<SubItemAdapter.SubItemViewHolder> {
private ArrayList<SubItem> subItemList;
private SubItemController controller;
SubItemAdapter(ArrayList<SubItem> subItemList) {
this.subItemList = subItemList;
this.controller = SubItemController.getController();
}
@NonNull
@Override
public SubItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_sub_item, viewGroup, false);
return new SubItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull SubItemViewHolder holder, int i) {
SubItem currentItem = subItemList.get(i);
holder.workoutName.setText(currentItem.getmWorkoutName());
holder.workoutNum.setText(currentItem.getWorkoutNum());
currentItem.setSpinner(holder.workoutUnit);
// store the spinner in the DetailItem object
currentItem.setSpinner(holder.workoutUnit);
// store DetailItem object in the array
}
@Override
public int getItemCount() {
return subItemList.size();
}
class SubItemViewHolder extends RecyclerView.ViewHolder {
EditText workoutName;
EditText workoutNum;
Spinner workoutUnit;
SubItemViewHolder(View itemView) {
super(itemView);
workoutName = itemView.findViewById(R.id.workoutname);
workoutNum = itemView.findViewById(R.id.number);
workoutUnit = itemView.findViewById(R.id.unitspinner);
workoutUnit.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapter, View v,
int position, long id) {
// On selecting a spinner item
String sStep = adapter.getItemAtPosition(position).toString();
workoutUnit.setSelection(position);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
public void addExercise(SubItem exercise) {
controller.getListExercise().add(exercise);
notifyItemInserted(getItemCount());
}
}
SubItemController
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class SubItemController {
private ArrayList<SubItem> exampleList;
private ArrayList<SubItem> initialList;
private static SubItemController controller;
private SubItemAdapter adapter;
public SubItemController(){
initMovieList();
}
private ArrayList<SubItem> initMovieList(){
if (this.exampleList == null) {
this.exampleList = new ArrayList<>();
exampleList.add(new SubItem("","", ""));
}
return this.exampleList;
}
public void addSubItem() {
SubItem item = new SubItem("","","");
exampleList.add(item);
}
public ArrayList<SubItem> buildInitialList() {
initialList = new ArrayList<SubItem>();
initialList.add(new SubItem("","",""));
return initialList;
}
public ArrayList<SubItem> getListExercise() {
return exampleList;
}
public static SubItemController getController(){
if(controller == null){
controller = new SubItemController();
}
return controller;
}
}
Вещь
import android.widget.Spinner;
import java.util.ArrayList;
import java.util.List;
public class Item {
private String mstructure;
private String mtype;
private ArrayList<SubItem> mList;
private Spinner structureSpinner;
private Spinner typeSpinner;
private SubItemController subItemController;
public Item(String structure, String type, ArrayList<SubItem> List){
mstructure = structure;
mtype = type;
mList = List;
subItemController = new SubItemController();
}
public Spinner getStructureSpinner() {
return structureSpinner;
}
public void setStructureSpinner(Spinner structureSpinner) {
this.structureSpinner = structureSpinner;
}
public Spinner getTypeSpinner() {
return typeSpinner;
}
public void setTypeSpinner(Spinner typeSpinner) {
this.typeSpinner = typeSpinner;
}
public String getMstructure() {
return mstructure;
}
public void setMstructure(String mstructure) {
this.mstructure = mstructure;
}
public String getMtype() {
return mtype;
}
public void setMtype(String mtype) {
this.mtype = mtype;
}
public ArrayList<SubItem> getmList() {
return subItemController.getListExercise();
}
public void addExercise() {
subItemController.addSubItem();
}
}
ItemAdapter
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> {
private RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
private ArrayList<Item> itemList;
private ArrayList<SubItem> subItemList = new ArrayList<>();
private SubItemAdapter adapter;
ItemAdapter(ArrayList<Item> itemList) {
this.itemList = itemList;
adapter = new SubItemAdapter(subItemList);
}
@NonNull
@Override
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_item, viewGroup, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ItemViewHolder itemViewHolder, int i) {
Item item = itemList.get(i);
// Create layout manager with initial prefetch item count
LinearLayoutManager layoutManager = new LinearLayoutManager(
itemViewHolder.rvSubItem.getContext(),
LinearLayoutManager.VERTICAL,
false
);
layoutManager.setInitialPrefetchItemCount(item.getmList().size());
// Create sub item view adapter
SubItemAdapter subItemAdapter = new SubItemAdapter(item.getmList());
itemViewHolder.rvSubItem.setLayoutManager(layoutManager);
itemViewHolder.rvSubItem.setAdapter(subItemAdapter);
itemViewHolder.rvSubItem.setRecycledViewPool(viewPool);
}
@Override
public int getItemCount() {
return itemList.size();
}
class ItemViewHolder extends RecyclerView.ViewHolder {
public Spinner structureSpinner;
public Spinner typeSpinner;
private RecyclerView rvSubItem;
private Button addExerciseButton;
private SubItemAdapter adapter;
ItemViewHolder(View itemView) {
super(itemView);
structureSpinner = itemView.findViewById(R.id.strucure_spinner);
typeSpinner = itemView.findViewById(R.id.type_spinner);
rvSubItem = itemView.findViewById(R.id.rv_sub_item);
addExerciseButton = itemView.findViewById(R.id.addExerciseButton);
addExerciseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
adapter.addExercise(new SubItem("","",""));
}
});
}
}
}
Основная деятельность
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Button addExerciseButton;
private Button addSetButton;
private SubItemController subItemController;
int numOfItem = 0;
int numOfSubItem = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RecyclerView rvItem = findViewById(R.id.rv_item);
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
ItemAdapter itemAdapter = new ItemAdapter(buildItemList());
rvItem.setAdapter(itemAdapter);
rvItem.setLayoutManager(layoutManager);
addSetButton = findViewById(R.id.addSetButton);
addSetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addSet();
ItemAdapter itemAdapter = new ItemAdapter(buildItemList());
rvItem.setAdapter(itemAdapter);
}
});
}
private ArrayList<Item> buildItemList() {
subItemController = new SubItemController();
ArrayList<Item> itemList = new ArrayList<>();
for (int i=0; i<numOfItem; i++) {
Item item = new Item("","",subItemController.getListExercise());
itemList.add(item);
}
return itemList;
}
private void addSet() {
numOfItem++;
}
}
Activity_main
<LinearLayout
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"
tools:context=".MainActivity"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:text="Add Set"
android:id="@+id/addSetButton"
android:layout_gravity="center"
/>
</LinearLayout>
layout_item
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#f3f3f3"
app:cardElevation="8dp"
android:layout_margin="12dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Spinner
android:id="@+id/strucure_spinner"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginStart="50dp"
android:entries="@array/workoutStructure"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Spinner
android:id="@+id/type_spinner"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginEnd="50dp"
android:entries="@array/workoutType"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sub_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/addExerciseButton"
android:layout_gravity="center"
android:text="Add Exercise"
/>
"
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
layout_sub_item
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="@+id/addworkoutcardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/structurespinner"
android:padding="5dp"
app:cardCornerRadius="4dp"
app:layout_constraintTop_toBottomOf="@+id/structurespinner"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/number"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_toRightOf="@+id/workoutname"/>
<EditText
android:id="@+id/workoutname"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginEnd="19dp"
android:ems="10"
android:layout_marginRight="19dp" />
<Spinner
android:id="@+id/unitspinner"
android:layout_width="120dp"
android:layout_height="50dp"
android:layout_marginStart="7dp"
android:layout_toRightOf="@+id/number"
android:entries="@array/workoutUnit"
android:layout_toEndOf="@+id/number"
android:layout_marginLeft="7dp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</FrameLayout> ```