Динамически добавлять вложенные элементы во вложенный recyclerview с помощью кнопки

У меня есть вложенный 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> ```

person Jeff    schedule 05.06.2020    source источник


Ответы (1)


in ItemAdapter

 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 = new SubItemAdapter(subItemList);
            adapter.addExercise(new SubItem("","",""));
        }
    });

Вы должны сделать новый адаптер (SubItemAdapter)

person Javad Dehban    schedule 05.06.2020