마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

리사이클러뷰 안에 null object reference 에러

0 추천

코드를 분석해봐도 null reference가 왜 생기는지 잘 모르겠습니다..

[에러 코드]

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference
        at com.mango.wellbeingdiary.main.health.log.HealthTodayLog.addSets(HealthTodayLog.java:101)
        at com.mango.wellbeingdiary.main.health.log.HealthTodayLog.access$000(HealthTodayLog.java:31)
        at com.mango.wellbeingdiary.main.health.log.HealthTodayLog$1.onAddItem(HealthTodayLog.java:87)
        at com.mango.wellbeingdiary.main.adapter.RoutineViewHolder$1.onClick(RoutineViewHolder.java:49)
        at android.view.View.performClick(View.java:7448)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

 

[RoutineViewHolder]

public class RoutineViewHolder extends RecyclerView.ViewHolder {
    ArrayList<SetsList> list = new ArrayList<>();
    public interface Listener {
        void onAddItem(Routine routine);
    }

    private final TextView exerciseText;
    private final Button addBtn;
    private final RecyclerView setsRcv;

    private final HealthSecondRecyclerViewAdapter adapter;

    public RoutineViewHolder(@NonNull View itemView) {
        super(itemView);

        exerciseText = itemView.findViewById(R.id.exerciseTitle);
        addBtn = itemView.findViewById(R.id.addSetBtn);
        setsRcv = itemView.findViewById(R.id.healthFirstRecyclerView);

        adapter = new HealthSecondRecyclerViewAdapter(list);
        setsRcv.setAdapter(adapter);

    }

    public void bind(Routine routine, Listener listener) {
        exerciseText.setText(routine.getExerciseText());
        adapter.setItems(routine.getItemCount());
        addBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.onAddItem(routine);
            }
        });
    }
}

 

[healthTodayLog]

public class HealthTodayLog extends AppCompatActivity {
    Toolbar toolbar;
    String fileName; // 선택된 날짜의 파일 이름
    ArrayList<Routine> list = new ArrayList<>();
    private HealthFirstRecyclerViewAdapter routineAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.health_today_log);

        long now = System.currentTimeMillis();
        Date date = new Date(now);
        SimpleDateFormat dateFormat = new SimpleDateFormat("Y년 M월 d일");
        String getTime = dateFormat.format(date);

        /* 툴바 설정 */
        toolbar = findViewById(R.id.todayLogToolbar);
        setSupportActionBar(toolbar); // 툴바를 앱바로 지정.
        ActionBar actionBar = getSupportActionBar(); // 툴바에 대한 참조 획득하기
        actionBar.setTitle(getTime + " 운동기록");

        // 캘린더 뷰를 클릭해서 들어왔으면 0번 로직
        // 헬스 로그 등록을 클릭해서 들어왔으면 1번 로직.
        Intent intent = getIntent();
        int check = intent.getIntExtra("check", 999);
        if(check == 0) {
            int year = intent.getIntExtra("year", 2021);
            int month = intent.getIntExtra("month", 1);
            int day = intent.getIntExtra("day", 1);

            actionBar.setTitle(year + "년 " + month + "월 " + day + "일 운동기록");

            //readLog로 넘어감.

        } else if(check == 1) {
            int c = 1;
            String s = intent.getStringExtra(String.valueOf(0));
            while (s != null) {
                /* 중복을 제거 하기 위해서 list에 s가 들어가 있는지 확인함. */
                if(!list.contains(s)) {
                    Routine newRoutine = new Routine(s);
                    list.add(newRoutine);
                }
                s = intent.getStringExtra(String.valueOf(c++));
            }

            RecyclerView recyclerView = findViewById(R.id.todayLogRectyclerView);

            LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
            recyclerView.setLayoutManager(linearLayoutManager);

            HealthFirstRecyclerViewAdapter adapter = new HealthFirstRecyclerViewAdapter(list);
            adapter.setRoutineListener(new RoutineViewHolder.Listener() {
                @Override
                public void onAddItem(Routine routine) {
                    addSets(routine);
                }
            });
            recyclerView.setAdapter(adapter);
        }

        //readLog(year, month, day);

        /* 로그 등록하고 들어왔으면 아래 로직 */
        //saveLog()
    }

    private void addSets(Routine routine) {
        ArrayList<SetsList> setsLists = routine.getSetsItems();
        setsLists.add(SetsList.newEmptySetsItem());
        routineAdapter.updateRoutine(routine);
    }

 

[Routine.class]

public class Routine {
    private String listText;
    private Button button;
    private ArrayList<SetsList> setsList;

    // 초기화를 위한 생성자
    public <E> Routine(String equipmentName, ArrayList<E> es) {
        listText = equipmentName;
        setsList = (ArrayList<SetsList>) es;
    }

    // 루틴이 추가 될 때 하위 어댑터를 받기 위해서 ArrayList가 필요함.
    public static Routine newEmptyRoutine(String equipmentName) {
        return new Routine(equipmentName, new ArrayList<>());
    }

    public Routine(String text) { this.listText = text; }

    public Routine(Button button) { this.button = button; }

    public String getExerciseText() { return listText;}

    public Button getBtn() { return button; }

    public ArrayList<SetsList> getItemCount() { return setsList; }

    public ArrayList<SetsList> getSetsItems() { return setsList; }
}

 

매력적인수박 (670 포인트) 님이 2021년 7월 26일 질문

1개의 답변

0 추천
 
채택된 답변

코드로 봐서는 
 

private void addSets(Routine routine) {
        ArrayList<SetsList> setsLists = routine.getSetsItems();
        setsLists.add(SetsList.newEmptySetsItem());
        routineAdapter.updateRoutine(routine);
    }

위 부분에서 setLists가 널인 것 같아보이는데요. 왜 널이 들어가는지는 님이 올리신 코드에서는 알 수가 없을 듯 해요. 디버깅을 해보시고  Roune이 생성되는 코드들을 점검해 보세요.

spark (227,470 포인트) 님이 2021년 7월 27일 답변
매력적인수박님이 2021년 7월 27일 채택됨
...