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

프래그먼트 getArgument시 null object 에러 질문좀드립니다

0 추천

현제 메인 액티비티에서 프래그먼트로 api에서 json 형식의 데이터를 gson 을 이용해서 자바 객체로 변환한후

이 데이터를 setArgument를 사용해 프래그먼트로 전달하는걸 하고 있는데요..

gson으로 데이터를 받아 데이터까지는 확인했습니다,,

그런데 이걸 프래그먼트쪽으로 보내면 getArgument에서 자꾸 null object 에러가나는데.. 이유를 잘 모르겠습니다

 

MainActivity.java

 

 

 

 

 

MovieFragment.java

// JSON으로 받고 GSON으로 자바 객체화한 데이터를 보낼 함수. (프래그먼트 생성 후 Bundle 이용)
public static MovieFragment newInstance(MovieViewModel mvm) {
    MovieFragment fragment = new MovieFragment();
    Bundle bundle = new Bundle();
    bundle.putParcelable("movie", mvm);
    fragment.setArguments(bundle);

    return fragment;
}

// newInstance에서 보낸 데이터 받기
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Bundle bundle = this.getArguments();
    if(getArguments() != null) {
        movieData = bundle.getParcelable("movie");
        Log.d("전달 데이터 확인용", movieData.title);
    }
    else
        Log.d("onCreate()", "getArgument() : NULL");
}
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        final ViewGroup rootView =(ViewGroup)inflater.inflate(R.layout.fragment_movie, container, false);

        items = new ArrayList<>();
        pager = rootView.findViewById(R.id.pager);
        adpater = new MovieListAdapter();



        // 상세보기 버튼 구현 - 어댑터에 91번코드, 구현을 외부에서 처리
        adpater.setOnItemClickListener(new MovieListAdapter.OnDetailBtnClickListener() {
            @Override
            public void OnItemCick(View v) {
                if(fragmentCallback != null) {
                    fragmentCallback.replaceFragment(rootView, R.id.action_nav_movie_to_nav_detail);
                }
            }
        });

        // 아이템 추가
        items.add(addMovieList(1)); // 편의상 1페이지부터라고 칭함
        items.add(addMovieList(2));


        adpater.setItems(items); // ArrayList<MovieViewModel>을 통째로 전달
        adpater.notifyDataSetChanged();

        pager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
        pager.setAdapter(adpater);

        // 뷰페이저 좌우 프리뷰 구현1
        pager.setClipToPadding(false);
        pager.setClipChildren(false);
        pager.setOffscreenPageLimit(items.size());


        return rootView;
    }

 

onCteate에서 실행도 해보고

onCreateView에서 실행도 해봤는데 잘 안되네요.. 원인이 뭔지 알 수있을지요..ㅜ

 

참고로 앱은

메인액티비티는 Navigation Drawer(내비게이션 컴포넌트)로 되어있고
영화 목록들은 내비게이션 컴포넌트의 내비게이션 그래프의 프래그먼트에

viewpager2로 구현되어있습니다. 이 뷰페이저2를 이루는 아이템들은 리사이클러뷰로 구성되어있습니다..

 

감사합니다.

 

 

 

 

codeslave (3,940 포인트) 님이 2020년 10월 31일 질문

1개의 답변

0 추천

코드상으로는 이상은 없어 보이는데, 혹시 디버깅은 해보셨나요? bundle에 값은 들어가는데  못 읽어 오는 것인지, 값조차 안들어간건지. 값이 bundle에 들어가지 않았다면, JSON 파싱이 잘못 되었을 가능성이 있구요. 사용하고 계시는 네트워킹 라이브러리가 뭔가요? SpringClient 처럼 보이긴 하는데... 이 라이브러리가 Exception을 캐취하고 던져 주지 않으면, JSON 파싱 에러가 나더라도 앱이 종료되지는 않겠죠. 아마도 에러 콜백에 에러메세지가 출력될 것 처럼 보이네요. 확인해 보시길...

궁금한게 있는데, 왜 processResponse 메소드에서 왜 MoviewFragment.newInstance(item) 를 두번 호출하고 계시나요?

참고로 MoviewViewModel 은 적합하지 않은 클래스 이름입니다. 저는 그 코드를 보고 좀 놀랐거든요. 안드로이드에 ViewModel 클래스가 있는데  보통은 Model-View-View-Model 패턴을 구현할 때 상속받아 쓰는데, 처음에는 MoviewViewModel을 프레그먼트에 전달하나 하고 의아했었거든요. 좋은 네이밍은 코드의 가독성을 위해 정말 정말 중요합니다. 전세계의 내노라 하는 프로그래머들이 첫번째로 강조하는게 네이밍입니다. 클래스나 메소드가 님이 어떤의도로 작성했는지를 말해줄 수 있어야 하고 그것만 보고도 어떤 기능을 수행하는지 알 수 있도록 이름을 지어야 합니다. 이름이 적합할 때 까지 계속 좋은 이름을 고민하셔야 해요. 이렇게 하다보면 자연스럽게 코드를 좀 더 모듈화해서 짜기가 쉬워집니다. 왜냐면 클래스나 메소드의 이름이 암시하는 기능만 해당 부분에 넣게 되니까요.

네이밍과 관련해서 한가지 팁은, 님이 이미 아래처럼 님의 의도와 기능을 주석을 통해 해 놓았습니다.  그럼, 이 주석에 해당하는 부분을 메소드로 만드세요. 메소드 이름은 님이 단 주석을 사용하면 되구요. 그럼, 주석도 필요없고 코드의 가독성도 자연스럽게 높아집니다. 물론, 아래코드는 유티릴티 메소드로 빼면 여기저기서 재사용이 가능하겠죠.

// 뷰페이저 좌우 프리뷰 구현1
pager.setClipToPadding(false);
pager.setClipChildren(false);
pager.setOffscreenPageLimit(items.size());

private void makeViewPagerPreview(pageSize: Int) {
    pager.setClipToPadding(false);
    pager.setClipChildren(false);
    pager.setOffscreenPageLimit(pageSize);
}

 

 

spark (227,470 포인트) 님이 2020년 10월 31일 답변
spark님이 2020년 10월 31일 수정
newInstance 두번간이유는 뒤에껀 원래 지웠어야하는대 올리면서 안지웠네요..
딴데서보길 에러나는 이유가 뭐.. comit을하는데 replace, add remove등 프래그먼트 변화가 없어서 그럴수 있다고해서 혹시나해서 살험한다고 넣어본겁니다.원래는 없는 코드에요
결과는 마찬가지그요
클래스이름같은건 수정하겠습니다.
네트워킹 라이브러리는 volley를 사용했습니다 json파싱은 에러는 아닌거같은게..
g본문에도 적었지만 json 포맷을 gson으로 자바객체화한후 안에 있는 데이터를 디버깅 및 로그해서 출력해보니 나오는걸 확인했습니다..
getArgument에서 bundle에서 null이 찍혀요ㅜㅜㅜ
디버깅을 어떻게 하셨는지는 정확하게 알 수 없지만, 두가지를 확인해 보셔야 합니다.  값이 안들어간 것인지, 값은 들어갔으나 못꺼내는 것인지. Bundle  안에 movie키가 존재하는지, movie키가 존재한다면 값이 들어 있는지, 아니면 null인지. 그리고 newInstance로 넘기는 mvm 에 원하시는 값이 존재하는지도요. 로그를 출력하지 마시고 브레이크 포인트를 걸어서 디버거로 확인해 보시는게 정확합니다.
...