리사이클러뷰 notifydatasetchanged() NullPointerException

조회수 550회

저는 친구들과 안드로이드 공부를 하고 있는 사람입니다.

하지만 제가 어리석어서 친구들과 같이 만든 부분을 해결할 방법을 모르겠습니다.

지금 프래그먼트랑 리사이클러뷰 부분에서 큰 어려움을 겪어 같이 만들어보려고 했던 프로젝트가 3주째 진전이 없네요.

코드입니다.

package com.example.dutpaytest;

import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class testbase_A01 extends Fragment implements OnBackPressedListener {
    Button btnHistory, btnStart;
    ImageButton ibtnPlus;
    final String[] scanArray = {"스캔시작", "갤러리로 이동"};
    private ArrayList<UserActivity> arrayList;
    public User_extends user_extends; // private으로 지정할 경우 사용하지 않은 함수라고 해서 public으로 바꿔놓음.
    private RecyclerView recyclerView;
    private LinearLayoutManager linearLayoutManager;
    A00_MainActivity A00;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        View root = inflater.inflate(R.layout.a01_start_0, container, false);

        return root;
    }

    private void StartEvent() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("영수증 스캔");
        builder.setItems(scanArray, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                switch (scanArray[i]) {
                    case "스캔시작":
                        Toast.makeText(getActivity().getApplicationContext(), "스캔을 실행합니다.",
                                Toast.LENGTH_SHORT).show();
                        Fragment fragment = new testbase_A02();
                        ((base) getActivity()).replaceFragment(fragment);
                        break;
                    case "갤러리로 이동":
                        Toast.makeText(getActivity().getApplicationContext(), "스캔 할 사진을 골라주세요.",
                                Toast.LENGTH_SHORT).show();

                        // 파일 퍼미션 허용시 아래 실행
                        Intent gallaryIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://media/internal/images/media"));
                        startActivity(gallaryIntent);
                        /*
                        퍼미션 거절 시
                        Toast.makeText(getApplicationContext(), "엑세스가 거부 되었습니다.",
                                Toast.LENGTH_SHORT).show();

                        View.OnClickListener onClickListener = new View.OnClickListener() {
                            private static final String REQUEST_PICTURE = "";

                            @Override
                            public void onClick(View v) {
                                Intent intent = new Intent(Intent.ACTION_PICK);
                                intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");

                                //intent.setType("image/*");
                                //intent.setAction(Intent.ACTION_SCREEN_ON);
                                startActivityForResult(intent, gallaryReqCode);
                            }
                        };
                        */
                        break;
                }
            }

        });
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    // 앱 종료 다이얼 로그 처리 함수
    public void EndEvent() {
        final Dialog endDialog = new Dialog(getContext());
        endDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        endDialog.setContentView(R.layout.a01_4_end2vent);

        ImageView testComm = (ImageView) endDialog.findViewById(R.id.testComm);
        Button btnY = (Button) endDialog.findViewById(R.id.btnY);
        Button btnN = (Button) endDialog.findViewById(R.id.btnN);

        endDialog.show();

        // 광고 처리
        testComm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent commercialIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://mma.go.kr/"));
                startActivity(commercialIntent);
            }
        });
        // 네, 아니오 버튼
        btnY.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                endDialog.dismiss();
                getActivity().finish();
            }
        });
        btnN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                endDialog.dismiss();
                return;
            }
        });
    }

    private void PlusUser() {
        final Dialog addUser = new Dialog(getActivity());
        addUser.setContentView(R.layout.a01_1_plus);
        addUser.setTitle("인원 추가 화면");
        Button add = (Button) addUser.findViewById(R.id.btnadd);
        final EditText addName = (EditText) addUser.findViewById(R.id.ETaddname);

        add.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {

                String name = addName.getText().toString();

                arrayList.add(new UserActivity(R.color.colorAccent, name));
                user_extends.notifyDataSetChanged();
                user_extends.setArrayList(arrayList, getActivity());
                recyclerView.setAdapter(user_extends);
                Toast.makeText(getActivity().getApplicationContext(), "추가", Toast.LENGTH_SHORT).show();

                addUser.dismiss();

            }
        });
        ((base) getActivity()).createDialog(addUser);
    }

    @Override
    public void onStart() {
        btnHistory = getView().findViewById(R.id.btnHistory);
        btnStart = getView().findViewById(R.id.btnStart);
        ibtnPlus = getView().findViewById(R.id.ibtnPlus);

        recyclerView = (RecyclerView) getActivity().findViewById(R.id.layoutContainer);
        linearLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(linearLayoutManager);

        arrayList = new ArrayList<>();


        recyclerView.setAdapter(user_extends);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext(), LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(linearLayoutManager);
        super.onStart();


        // 기록보기 버튼(Main -> History 전환)
        btnHistory.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent historyIntent = new Intent(getActivity().getApplicationContext(), A06_HistoryActivity.class);
                startActivity(historyIntent);
            }
        });

        // 시작 버튼
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StartEvent();
            }
        });

        // 인원추가 버튼
        ibtnPlus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //인원추가 버튼 처리 코드
                PlusUser();
                Toast.makeText(getActivity().getApplicationContext(), "인원이 추가되었습니다.", Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        //A00.setOnBackPressedListener(this);
    }

    @Override
    public void onBackPressed() {
        EndEvent();
    }
}

로그캣입니다.

    --------- beginning of crash
2021-03-01 18:27:09.695 23444-23444/com.example.dutpaytest E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.dutpaytest, PID: 23444
    java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.dutpaytest.User_extends.notifyDataSetChanged()' on a null object reference
        at com.example.dutpaytest.testbase_A01$5.onClick(testbase_A01.java:147)
        at android.view.View.performClick(View.java:8160)
        at android.widget.TextView.performClick(TextView.java:16221)
        at android.view.View.performClickInternal(View.java:8137)
        at android.view.View.access$3700(View.java:888)
        at android.view.View$PerformClick.run(View.java:30236)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:8506)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

여기 있는 내용으로 부족하다면 말해주세요. 바로 확인하고 올리겠습니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • User_extends 가 recyclerview 에 연결되는 어댑터 클래스를 정의하신것같아보이는데요. 이걸 초기화 하는 곳이 없네요. 초기화 되어있지 않기떄문에 user_extends 변수가 현재 null 입니다. 그래서 NullPointerException 이 뜬것이고요.

    user_extends 변수를 초기화 해주시기 바랍니다.

    • 감사합니다. 변수가 초기화되지 않아서 그런 것이라고 얼추 예상을 했었는데 또 초기화할 방법을 모르겠네요. 어댑터 유형으로 초기화 시키려고 생각 중인데 어댑터 유형보다 더욱 유용한 방법이 있을까요? 알 수 없는 사용자 2021.3.4 21:19
    • 일반적으로 리사이클러뷰 어댑터를 상속받으셨다면 new 사용하셔서 초기화하시면 됩니다 김은기 2021.3.5 01:55

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)