findViewByID는 null을 반환


251

우선 : 예,이 주제에 대한 다른 모든 스레드를 읽습니다. 그리고이 사이트의 사람들뿐만 아니라 ... (알다시피 조금 실망합니다)

그들 대부분은 XML 파일 android:id대신 사용하는 조언을 제공 id합니다. 나는했다.

다른 사람들과 View.findViewById는 다른 방식으로 작동합니다 Activity.findViewById. 나도 그 일을 처리했다.

location_layout.xml에서는 다음을 사용합니다.

<FrameLayout .... >
    <some.package.MyCustomView ... />

    <LinearLayout ... >
        <TextView ...
            android:id="@+id/txtLat" />
        ...
    </LinearLayout>
</FrameLayout>

내 활동에서 나는 :

...
setContentView( R.layout.location_layout );

내 맞춤보기 수업에서 :

... 
TextView tv = (TextView) findViewById( R.id.txtLat );

는을 반환합니다 null. 이렇게하면 내 활동이 제대로 작동합니다. 그래서 어쩌면 때문에의의 Activity.findViewByIdView.findViewById차이. 그래서 컨텍스트를 세관 뷰 생성자에 로컬로 저장하고 시도했습니다.

...
TextView tv = (TextView) ((Activity) context).findViewById( R.id.txtLat );

또한 반환했습니다 null.

그런 다음 사용자 정의보기를 ViewGroup대신 확장하도록 View변경하고 location_layout.xmlTextView사용자 정의보기의 직접적인 자식으로 변경하여 View.findViewById예상대로 작동하도록했습니다. Suprise : 아무것도 해결하지 못했습니다.

도대체 내가 뭘 잘못하고 있니?

의견을 보내 주셔서 감사합니다.


6
프로젝트가 손상된 경우에도 발생할 수 있습니다. 프로젝트를 정리하여 수정했습니다
Pacerier

1
잘못된 컨텍스트보기 감사를 통과 함
izzy

1
@Pacerier 감사합니다. 그게 내 문제를 해결했다. 나는 Xamarin에서 안드로이드 프로그래밍을 싫어하기 시작한다)
Artiom

@Pacerier "Clean project"도 내 문제를 해결했습니다. Dropbox가 프로젝트를 손상시킨 것 같습니다.
Kohki Mametani

답변:


271

null을 돌려주는

아마도 너무 일찍 전화했기 때문일 수 있습니다. 까지 기다 onFinishInflate()립니다. 다음은View 컨텐츠에 액세스 하는 사용자 정의를 보여주는 샘플 프로젝트 입니다.


67
세상에! 캔 트는 내가 아주 사소한 일에 며칠을 보낸다고 믿습니다. 나는 setContentView ()를 findViewById () 호출 위로 옮겼다. 감사!
agentcurry

2
@CommonsWare 올바른 프로젝트입니까? github.com/commonsguy/cw-advandroid/tree/master/Animation/…에
likejudo

1
@likejiujitsu : 2010 년에 그랬을 수도 있습니다. 나는 새로운 프로젝트에 대한 링크를 업데이트했습니다 onFinishInflate().
CommonsWare

3
findViewById 전에 setContentView를 호출했지만 여전히 null입니다. 나는 글고 치기를 참조하고
네온 Warge을

1
항상 고정 된 GitHub 커밋 (예 : github.com/commonsguy/cw-omnibus/tree/… )에 연결하고 repos 또는 rebase를 삭제하지 마십시오 ;-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

145

아마도 전화 findViewById하기 전에 전화하고 setContentView있습니까? 그런 경우에는 전화 시도 findViewById 후에 호출setContentView


1
그렇게 쉬운 실수는 쉽지 않지만 불행히도 이것은 내가 한 일입니다. 디버거는 오류가 내가 호출 한 실제 새로운 활동이 아닌 새로운 의도 행에 있다고 말했기 때문에 사용되지 않습니다. 감사!
edude05

6
실제로 잘못된 뷰를 가리키는 setContentView를 호출했기 때문에이 오류가 발생했습니다 ... 불행히도 컴파일러는 이러한 유형의 오류를 포착하지 않습니다.
HeatfanJohn

예, 실수로 setContentView를 삭제했으며 내 프로그램이 왜 부서지기 시작했는지 이해하지 못했습니다.
Ronen Festinger

100

다른 화면 밀도에 대해 여러 버전의 레이아웃이 없는지 확인하십시오. 기존 레이아웃에 새 ID를 추가 할 때이 문제가 발생했지만 hdpi 버전을 업데이트하는 것을 잊었습니다. 모든 버전의 레이아웃 파일을 업데이트하는 것을 잊어 버린 경우 일부 화면 밀도에서는 작동하지만 다른 버전에서는 작동하지 않습니다.


8
감사! 그거였다. (제 경우에는 다른 Android 버전의 여러 버전이 있습니다). 모든 레이아웃 파일의 상단과 하단에 거대한 주석을 달았지만 항상 잊어 버렸습니다. 이런 일이 발생하면 컴파일러에서 오류가 발생하거나 큰 경고가 발생하기를 바랍니다.
tiktak

딩 딩 딩 너무 감사합니다! 이 lol 위에 내 두뇌를 굽히고 있었다
Zach

21

사용자 정의보기에서 잘못된 수퍼 생성자를 호출하면 FindViewById가 널이 될 수 있습니다. ID 태그는 attr의 일부이므로 attr을 무시하면 ID가 삭제됩니다.

이것은 잘못 될 것입니다

public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context);
}

맞습니다

public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context,attrs);
}

1
매우 감사합니다! 그래서 부주의하게, 나는 심지어 내 IDE에 문제가 있다고 의심했다. 당신의 대답을 만나서 얼마나 운이 좋습니까?
EffectiveMatrix

사용자 정의보기를 만들 때이 실수를했습니다. 감사합니다, repkap11.
Andrew F.

15

내 경우, 나는 내 프로젝트에이 명하는 행동이 있었다, main.xml하고 main2.xml. 처음부터 main2의 복사본이었다 main, 나는 새로운 추가 될 때까지 모든 것이 잘 작동 TextViewmain2(가) 때문에, R.id.textview1응용 프로그램의 나머지 가능하게되었다. 그런 다음 표준 호출로 가져 오려고했습니다.

TextView tv = (TextView) findViewById( R.id.textview1 );

그리고 항상 null이었습니다. onCreate생성자에서 인스턴스가 아닌 main2다른 인스턴스를 인스턴스화 하고 있음이 밝혀졌습니다 . 나는했다 :

setContentView(R.layout.main);

대신에

setContentView(R.layout.main2);

나는 여기에 도착한 후에 사이트에서 이것을 알아 차렸다.


14

다른 곳에서 언급 한 고전적인 원인과 함께 :

  • setContentView()전에 전화했는지 확인하십시오findViewById()
  • id원하는 뷰 또는 레이아웃이 원하는지 확인하십시오setContentView()
  • id다른 레이아웃에서 실수로 복제되지 않도록하십시오

표준 레이아웃에서 사용자 정의보기에 대해 찾은 것이 있는데, 이는 문서와 반대입니다.

이론적으로 사용자 정의보기를 작성하여 레이아웃에 추가 할 수 있습니다 ( 여기 참조 ). 그러나 그러한 상황에서 때로는 id속성이 사용자 정의 뷰를 제외한 레이아웃의 모든 뷰에서 작동 한다는 것을 알았습니다 . 내가 사용하는 솔루션은 다음과 같습니다.

  1. 각 사용자 정의보기를 사용자 정의보기에서 FrameLayout원하는 것과 동일한 레이아웃 속성으로 바꿉니다 . 적절하게 id말해frame_for_custom_view .
  2. 에서 onCreate:

    setContentView(R.layout.my_layout);
    FrameView fv = findViewById(R.id.frame_for_custom_layout);
    MyCustomView cv = new MyCustomView(context);
    fv.addView(cv);

    프레임에 커스텀 뷰를 넣습니다.


"원하는 id가 setContentView ()에 제공 한 뷰 또는 레이아웃에 있는지 확인하십시오." 그러나 서브 뷰 인 경우 어떻게해야합니까? 부모보기를 시도한 다음 parentView.findById ()를 수행했지만 여전히 null을 반환합니다.
NaturalBornCamper

@naturalborncamper 예제 코드로 별도의 질문을 게시하면 살펴볼 것입니다.
Neil Townsend

고마워 Neil, 나는 이미 게시하고 누군가가 더 좋은 방법을 지적했지만 그것이 어떻게 작동해야 하는지를 정확히
NaturalBornCamper

9
    @Override
protected void onStart() {
         // use findViewById() here instead of in onCreate()
    }

6

ExpandableListView를 사용하고 제목에 따라이 질문에 답하는 사람들을위한 답변.

이 오류는 ExpandableListView 구현의 일부로 자식 및 그룹보기에서 TextView를 사용하려고 시도했습니다.

getChildView () 및 getGroupView () 메소드 구현에서 다음과 같은 것을 사용할 수 있습니다.

        if (convertView == null) {
            LayoutInflater inflater =  (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.child_layout, null);
        }

나는 이것을 여기 에서 발견 했다 .


5

Android / Eclipse를 처음 접했을 때 실수로 UI activity_main.xml대신 UI를 추가했습니다 fragment_main.xml. 알아 내기 위해 몇 시간이 걸 렸어요 ...


5

FWIW, 나는 누군가가 내가 필요로했던 것과 똑같은 방식으로 이것을 해결 한 것을 보지 못했습니다. 컴파일 타임에 불만은 없지만 런타임에 null보기를 얻고 적절한 순서로 항목을 호출했습니다. 즉, setContentView () 다음에 findViewById ()입니다. 문제는 내보기가 content_main.xml에 정의되어 있지만 내 activity_main.xml 에이 한 문장이 부족하다는 것이 밝혀졌습니다.

<include layout="@layout/content_main" />

activity_main.xml에 추가하면 더 이상 NullPointer가 없습니다.


조각을 붙여 넣을 때의 문제는 때로는 일부를 변경하는 것을 잊어 버리는 것입니다. 감사!
Pablo Quemé

3

나는이 같은 문제가 있었다. GridView에 대한 어댑터를 재정의하고 각 GridView 셀에 대해 고유 한 레이아웃을 지정할 수있는 타사 라이브러리를 사용하고있었습니다.

마침내 무슨 일이 있었는지 깨달았습니다. Eclipse는이를 표시하지 않았지만 GridView의 각 셀에 대해 라이브러리의 레이아웃 xml 파일을 계속 사용하고있었습니다. 내 사용자 지정 어댑터에서 런타임에 아니더라도 내 프로젝트의 xml 리소스를 사용하고 있음을 나타냅니다.

그래서 내가 한 일은 사용자 정의 XML 레이아웃과 ID가 여전히 라이브러리에 앉아있는 것과 다르고 프로젝트를 정리 한 다음 프로젝트에있는 올바른 사용자 정의 레이아웃을 읽기 시작하는 것이 었습니다.

요컨대, 써드 파티 라이브러리의 어댑터를 대체하고 어댑터가 사용할 고유 레이아웃 XML을 지정하는 경우주의하십시오. 프로젝트 내부의 레이아웃이 라이브러리의 파일 이름과 동일한 파일 이름을 가진다면 찾기 어려운 버그가 발생할 수 있습니다!


3

내 특별한 경우에는 바닥 글을 ListView에 추가하려고했습니다. onCreate ()에서 다음 호출이 널을 리턴했습니다.

TextView footerView = (TextView) placesListView.findViewById(R.id.footer);

바닥 글보기를 ID별로 찾지 않고 부풀 리도록 변경하면이 문제가 해결되었습니다.

View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false);

2

필자의 경우 ExpandableListView를 사용하고을 설정했습니다 android:transcriptMode="normal". 이로 인해 확장 가능 그룹의 하위 항목이 사라지고 목록 스크롤을 사용할 때 NULL 예외가 발생했습니다.


2

나에게 같은 활동에 대해 두 개의 XML 레이아웃이있었습니다. 하나는 세로 모드이고 하나는 가로입니다. 물론 나는 landscape xml에서 객체의 id를 변경했지만 세로 버전에서 동일한 변경을 잊어 버렸습니다. 하나를 변경하면 다른 xml과 동일하게 수행하거나 실행 / 디버그 할 때까지 오류가 발생하지 않으며 변경하지 않은 ID를 찾을 수 없습니다. 멍청한 실수, 왜 날 그렇게 처벌해야합니까?


2

레이아웃 리소스에서 활동 내용을 설정하십시오. 즉 setContentView(R.layout.basicXml);


2

위의 솔루션 외에도
tools:context=".TakeMultipleImages" 레이아웃의 mainfest.xml 파일
android:name=".TakeMultipleImages"에서 동일한 활동 요소에 대해 동일한 값을 사용해야합니다 . 복사 및 붙여 넣기를 사용하여 새 활동을 작성할 때 발생합니다.


2

나는 같은 문제가 있지만 너희들과 나눌 가치가 있다고 생각합니다. 사용자 정의 레이아웃에서 viewById를 찾아야하는 경우 예를 들면 다음과 같습니다.

public class MiniPlayerControllBar extends LinearLayout {
    //code
}

생성자에서 뷰를 가져올 수 없습니다. 뷰가 팽창 한 후 findViewById를 호출해야합니다. 그것들은 당신이 무시할 수있는 방법입니다onFinishInflate


2

내 구체적인 사건을 여기에 던지기를 원했습니다. 누군가를 도울 수 있습니다.

내 Android UI XML에서 다음과 같이 지시문을 사용하고있었습니다.

부모보기 :

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:tag="home_phone"
    android:background="@color/colorPrimary">

    ...

    <include
        layout="@layout/retry_button"
        android:visibility="gone" />

자식보기 (retry_button) :

<com.foo.RetryButton
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/retry"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="140dp">

.findViewById (R.id.retry)는 항상 null을 반환합니다. 그러나 ID를 자식보기에서 include 태그로 옮기면 작동하기 시작했습니다.

고정 부모 :

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:tag="home_phone"
    android:background="@color/colorPrimary">

    ...

    <include
        layout="@layout/retry_button"
        android:id="@+id/retry"
        android:visibility="gone" />

고정 아동 :

<com.foo.RetryButton
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="140dp">

2

내 경우는 위와 같지 않으며 해결책이 없습니다. 내 레이아웃이 레이아웃 계층 구조에 너무 깊다고 가정합니다. 나는 그것을 한 단계 위로 움직 였고 더 이상 null이 아니었다.


나도 같은 문제가 있는데, 한 단계 높은 수준도 발견 할 수있다. 그것은 꽤 성가시다. 내가 원하는 메뉴를 만들 수 없어서 왜 그런 일이 일어나고 있는지 알고 싶다
NaturalBornCamper

잘 깊은 레이아웃 계층 구조는 안티 패턴이며 거의 항상 깨끗한 솔루션이 있습니다. 툴바 또는 탐색 창의 오버플로 메뉴에 대해 이야기하고 있습니까?
Deividas Strioga

탐색 서랍, 그룹에 메뉴 항목을 추가해도 작동하지 않는다는 점을 제외하고는 실제로 다른 질문을 게시했습니다. 모든 항목 끝에 추가하면됩니다. stackoverflow.com/questions/47955376/…
NaturalBornCamper

1

내 경우에는 레이아웃을 팽창 시켰지만 자식 뷰는 null을 반환했습니다. 원래 나는 이것을 가지고 있었다 :

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

    footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
    pbSpinner = (ProgressBar) findViewById(R.id.pbListviewFooter);
    tvText = (TextView) findViewById(R.id.tvListviewFooter);
    ...
}

그러나 다음과 같이 변경하면 효과가 있습니다.

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

    footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false);
    pbSpinner = (ProgressBar) footerView.findViewById(R.id.pbListviewFooter);
    tvText = (TextView) footerView.findViewById(R.id.tvListviewFooter);
    ...
}

핵심은 자식 뷰를 얻기 위해 이미 팽창 된 레이아웃을 구체적으로 참조하는 것이 었습니다. 즉, 추가 footerView:

  • footerView .findViewById ...

0

필자의 경험에 따르면 OnDestroyView 이후에 코드가 호출 될 때 (프래그먼트가 백 스택에있을 때) 발생할 수 있습니다 .BroadCastReceiver에서 입력시 UI를 업데이트하는 경우이 경우인지 확인해야합니다 .


0

레이아웃을 부 풀리십시오! (ID가 포함되어 있음)

필자의 경우 findViewById ()는 요소가 작성된 레이아웃이 팽창되지 않았기 때문에 null을 반환했습니다 ...

예 : fragment_layout.xml

<ListView
android:id="@+id/listview">

inflater.inflate (R.layout.fragment_layout, ..., ...)을 수행하지 않았기 때문에 findViewById (R.id.listview)가 null을 반환했습니다. 그 전에.

이 답변이 일부 도움이 되길 바랍니다.


0

내 수정은 프로젝트를 청소하는 것이 었습니다.


0

findViewById는 Fragment 내부에 있으면 null을 반환 할 수도 있습니다. 여기에 설명 된대로 : Fragment의 findViewById

getView ()를 호출하여 Fragment 내부의 최상위 View를 반환해야합니다. 그런 다음 레이아웃 항목 (버튼, 텍스트 뷰 등)을 찾을 수 있습니다.


0

내했습니다, 그래서 나는 .. 일하는 위의 아무것도의 모든 해봤 이미지 뷰의 정적을 public static ImageView texture; 하고 texture = (ImageView) findViewById(R.id.texture_back);, 나는 그것이 비록 좋은 방법이라고 생각하지 않지만이 정말 내 경우 근무 :)


미안 해요, 난 정적 뷰가 나쁜 아이디어라고 생각
vuhung3990

0

필자의 경우 부모 객체에서 부모가 인스턴스화 한 어댑터 객체로 호출을 이동하면 findViewById가 null을 반환했습니다. 성공하지 않고 여기에 나열된 트릭을 시도한 후 findViewById를 다시 상위 오브젝트로 이동하고 어댑터 오브젝트 인스턴스화 중에 매개 변수로 결과를 전달했습니다. 예를 들어 부모 객체 에서이 작업을 수행했습니다.

 Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);

그런 다음 어댑터 객체를 만드는 동안 hdSpinner를 매개 변수로 전달했습니다.

  mTransactionAdapter = new TransactionAdapter(getActivity(),
        R.layout.transactions_list_item, null, from, to, 0, hdSpinner);

0

내 활동 ID의 필드 중 하나가 다른 활동의 id와 일치하기 때문에 충돌이 발생했습니다. 나는 고유 한 ID를 부여하여 그것을 고쳤다.

내 loginActivity.xml 비밀번호 필드 ID는 "password"입니다. 내 등록 활동에서 방금 id r_password를 제공하여 문제를 해결 한 다음 null 객체를 반환하지 않았습니다.

password = (EditText)findViewById(R.id.r_password);

0

에 대한 사용자 정의보기를 수행하려고 할 때 비슷한 문제에 직면했습니다. ListView .

나는 이것을 간단하게 해결했다.

public View getView(int i, View view, ViewGroup viewGroup) {

    // Gets the inflater
    LayoutInflater inflater = LayoutInflater.from(this.contexto);

    // Inflates the layout
    ConstraintLayout cl2 = (ConstraintLayout) 
    inflater.inflate(R.layout.custom_list_view, viewGroup, false);

    //Insted of calling just findViewById, I call de cl2.findViewById method. cl2 is the layout I have just inflated. 
     TextView tv1 = (TextView)cl2.findViewById(cl2);

0

디버깅하고 문제를 찾는 방법 :

  • 활동에서 모든 findViewById를 주석 처리하십시오.
  • onCreate 및 setContentView를 제외한 모든 것을 주석 처리하십시오.
  • 프로젝트를 실행하고 레이아웃이 설정되어 있는지 확인하십시오

제 경우에는 앱 모듈과 라이브러리 모듈 모두에서 activity_main.xml을 사용했습니다. 그래서 라이브러리에서 디자인 한 레이아웃 대신 위의 단계를 수행했을 때 앱 모듈 내부의 레이아웃이 팽창했습니다.

그래서 activity_main.xml 파일 이름을 activity_main_lib.xml로 변경했습니다.

따라서 전체 프로젝트에 중복 레이아웃 이름이 없는지 확인하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.