onCreate()에서 view로 접근 시 NullPointerException

조회수 2500회

이 질문은 hashcode에 빈번하게 올라오는 전형적인 질문 중에 하나입니다

튜토리얼에 따라 wizard를 사용하여 새 activity를 생성했습니다. Activity의 onCreate()내에서 View(findViewById() 메소드로 획득)를 통해 메소드 호출을 시도했는데 NullPointerException이 발생했습니다.

Activity의 onCreate():

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

    View something = findViewById(R.id.something);
    something.setOnClickListener(new View.OnClickListener() { ... }); // NPE 

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();
    }
}

Layout XML (fragment_main.xml):

<RelativeLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="packagename.MainActivity$PlaceholderFragment" >

    <View
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/something" />

</RelativeLayout>

1 답변

  • 좋아요

    0

    싫어요
    채택 취소하기

    튜토리얼이 오래된 것으로 보이네요. Wizard가 생성하는 코드를 선호하는 fragment 기반의 UI 말고 activity 기반의 UI를 생성해보세요.

    현재 view가 activity layout((activity_main.xml))이 아니라 fragment layout(fragment_main.xml)에 있습니다. Activity view hierarchy에서 해당 view를 찾기에는 앱의 라이프 사이클 상에서 onCreate()는 너무 이릅니다. 그래서 null값이 반환됐을 겁니다. Null인 상태에서 메소드 호출을 시도해서 NPE가 발생한 듯 해요.

    가장 추천해드리고 싶은 방법은 코드를 fragment onCreateView()로 옮긴 후에 활성화된 fragment layout rootView에서 findViewById() 메소드를 호출하는 방법입니다.

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
      View rootView = inflater.inflate(R.layout.fragment_main, container,
          false);
    
      View something = rootView.findViewById(R.id.something); // not activity findViewById()
      something.setOnClickListener(new View.OnClickListener() { ... });
    
      return rootView;
    }
    

    덧 붙이자면, fragment layout은 결국 activity view hierarchy의 일부분이 될 것이고 activity 내에서 findViewById() 메소드로도 찾을 수 있게 됩니다. 단 fragment 트랜잭션이 수행되고 난 후에 말이죠. 나머지 남겨진 fragment 트랜잭션은 onCreate()메소드가 수행된 후 super.onStart()에서 수행 됩니다.

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

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

(ಠ_ಠ)
(ಠ‿ಠ)