webentwicklung-frage-antwort-db.com.de

findViewByID gibt null zurück

Zunächst einmal: Ja, ich habe alle anderen Threads zu diesem Thema gelesen. Und nicht nur die von dieser Seite ... (Sie sind ein bisschen frustriert)

Bei den meisten von ihnen wird empfohlen, Android:id anstelle von id in der XML-Datei zu verwenden. Ich tat.

Von anderen habe ich erfahren, dass View.findViewById anders arbeitet als Activity.findViewById. Das habe ich auch gemacht.

In meinem location_layout.xml verwende ich:

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

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

In meiner Tätigkeit mache ich:

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

und in meiner benutzerdefinierten Ansichtsklasse:

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

was null zurückgibt. Auf diese Weise funktioniert meine Aktivität gut. Vielleicht liegt es an den Unterschieden Activity.findViewById und View.findViewById. Also habe ich den Kontext gespeichert, der lokal an den Konstruktor für die Zollansicht übergeben wurde, und versuchte es:

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

was auch null zurückgegeben hat.

Dann habe ich meine benutzerdefinierte Ansicht geändert, um ViewGroup statt View zu erweitern, und location_layout.xml so geändert, dass TextView ein direktes untergeordnetes Element meiner benutzerdefinierten Ansicht ist, sodass View.findViewById wie erwartet funktionieren sollte. Überraschung: es hat nichts gelöst.

Also, was zum Teufel mache ich falsch? 

Ich freue mich über Kommentare.

224
Thomas

das gibt null zurück

Möglicherweise weil Sie es zu früh anrufen. Warten Sie bis onFinishInflate(). Hier ist ein Beispielprojekt , das ein benutzerdefiniertes View zeigt, das auf seinen Inhalt zugreift.

245
CommonsWare

Möglicherweise rufen Sie findViewById auf, bevor Sie setContentView? Aufrufen. Versuchen Sie in diesem Fall, findViewByIdNACHaufzurufen setContentView.

130
Bayram Boyraz

Stellen Sie sicher, dass Sie nicht mehrere Versionen Ihres Layouts für unterschiedliche Bildschirmdichten haben. Ich habe dieses Problem einmal beim Hinzufügen einer neuen ID zu einem vorhandenen Layout festgestellt, habe aber vergessen, die HDpi-Version zu aktualisieren. Wenn Sie vergessen, alle Versionen der Layoutdatei zu aktualisieren, funktioniert sie für einige Bildschirmdichten, andere jedoch nicht.

89
Joe

In meinem Fall hatte ich zwei Aktivitäten in meinem Projekt, main.xml und main2.xml. Von Anfang an war main2 eine Kopie von main, und alles funktionierte gut, bis ich main2 um neue TextView fügte, sodass der R.id.textview1 für den Rest der App verfügbar wurde. Dann habe ich versucht, es per Standardruf abzurufen:

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

und es war immer null. Es stellte sich heraus, dass ich im onCreate-Konstruktor nicht main2, sondern den anderen instanziierte. Ich hatte:

setContentView(R.layout.main);

anstatt 

setContentView(R.layout.main2);

Ich habe das bemerkt, als ich hier auf der Baustelle angekommen bin.

15
infografnet

Neben den klassischen Ursachen, die an anderer Stelle erwähnt wurden:

  • Stellen Sie sicher, dass Sie setContentView() aufgerufen haben, bevor findViewById()
  • Vergewissern Sie sich, dass sich das von Ihnen gewünschte id in der Ansicht oder im Layout befindet, die Sie setContentView() angegeben haben.
  • Stellen Sie sicher, dass id nicht versehentlich in verschiedenen Layouts dupliziert wird

Ich habe eine für benutzerdefinierte Ansichten in Standardlayouts gefunden, die der Dokumentation widerspricht:

Theoretisch können Sie eine benutzerdefinierte Ansicht erstellen und einem Layout hinzufügen ( siehe hier ). Ich habe jedoch herausgefunden, dass in solchen Situationen das id-Attribut manchmal für alle Ansichten im Layout mit Ausnahme der benutzerdefinierten funktioniert. Die Lösung, die ich verwende, ist:

  1. Ersetzen Sie jede benutzerdefinierte Ansicht durch ein FrameLayout mit den gleichen Layout-Eigenschaften, die Sie für die benutzerdefinierte Ansicht benötigen. Geben Sie ein entsprechendes id an, sagen Sie frame_for_custom_view.
  2. In onCreate:

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

    dadurch wird die benutzerdefinierte Ansicht in den Rahmen eingefügt.

13
Neil Townsend

FindViewById kann null sein, wenn Sie in einer benutzerdefinierten Ansicht den falschen Superkonstruktor aufrufen. Das ID-Tag ist Teil von attrs. Wenn Sie also attrs ignorieren, löschen Sie die ID.

Das wäre falsch

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

Das ist richtig

public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context,attrs);
}
12
repkap11
    @Override
protected void onStart() {
         // use findViewById() here instead of in onCreate()
    }
8
Jonathan

Eine Antwort für diejenigen, die ExpandableListView verwenden und diese Frage basierend auf ihrem Titel ausführen. 

Ich hatte diesen Fehler beim Versuch, als Teil einer ExpandableListView-Implementierung mit TextViews in meinen untergeordneten und Gruppenansichten zu arbeiten.

In Ihren Implementierungen der Methoden getChildView () und getGroupView () können Sie etwa Folgendes verwenden.

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

Ich habe dieses hier gefunden.

6
Josh Metcalfe

Ich bin relativ neu in Android/Eclipse. Ich habe versehentlich die UI-Komponente zu activity_main.xml anstelle von fragment_main.xml hinzugefügt. Ich habe einige Stunden gebraucht, um das herauszufinden ...

5
lama12345

FWIW, ich sehe nicht, dass jemand dieses Problem so gelöst hat, wie ich es brauchte. Keine Beschwerden zur Kompilierzeit, aber zur Laufzeit habe ich eine Nullansicht erhalten und die Dinge in der richtigen Reihenfolge aufgerufen. Das ist, findViewById () after setContentView () . Das Problem stellte sich heraus, dass meine Ansicht in content_main.xml definiert ist, aber in meiner activity_main.xml fehlte mir diese eine Anweisung: 

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

Als ich das zu activity_main.xml hinzugefügt habe, kein NullPointer mehr. 

4
ferris

Mein Fall ist keiner wie oben, keine Lösung hat funktioniert. Ich gehe davon aus, dass meine Ansicht zu tief in die Layout-Hierarchie war. Ich habe es eine Ebene höher gesetzt und es war nicht mehr null.

3

In meinem speziellen Fall habe ich versucht, einer ListView eine Fußzeile hinzuzufügen. Der folgende Aufruf in onCreate () gab null zurück.

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

Wenn Sie dies ändern, um die Fußzeilenansicht aufzublähen, anstatt sie anhand der ID zu finden, wurde dieses Problem behoben.

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

Ich wollte nur meinen speziellen Fall hier einwerfen. Könnte jemandem weiterhelfen.

Ich habe die Direktive in meiner Android-Benutzeroberflächen-XML folgendermaßen verwendet:

Elternansicht:

<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" />

Unteransicht (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) würde immer null zurückgeben. Wenn ich die ID aus der untergeordneten Ansicht in das Include-Tag verschoben habe, funktionierte es.

Feste Eltern:

<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" />

Feststehendes Kind:

<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
John D.

In meinem Fall habe ich ExpandableListView verwendet und Android:transcriptMode="normal" gesetzt. Dies führte dazu, dass nur wenige Kinder in der erweiterbaren Gruppe verschwanden, und ich bekam eine NULL-Ausnahme, wenn ich die Liste scrollen ließ.

2
Jeevan

Legen Sie den Aktivitätsinhalt aus einer Layoutressource fest Dh. setContentView(R.layout.basicXml);

2
Ajay Takur

Ich hatte zwei XML-Layouts für dieselbe Aktivität - eines im Hochformat und eines im Querformat. Natürlich hatte ich die ID eines Objekts in der XML-Landschaft geändert, hatte aber vergessen, die gleiche Änderung in der Portrait-Version vorzunehmen. Stellen Sie sicher, dass Sie beim Ändern eines XML-Codes dasselbe mit der anderen XML-Datei tun. Andernfalls wird keine Fehlermeldung angezeigt, wenn Sie das Programm ausführen/debuggen und die ID nicht finden, die Sie nicht geändert haben. Oh dumme Fehler, warum musst du mich so bestrafen?

2
ColossalChris

Ich habe das gleiche Problem, aber ich denke, es lohnt sich, es mit Ihnen zu teilen ... Wenn Sie ViewById im benutzerdefinierten Layout suchen müssen, zum Beispiel:

public class MiniPlayerControllBar extends LinearLayout {
    //code
}

sie können die Ansicht nicht im Konstruktor abrufen. __ Sie sollten findViewById aufrufen, nachdem die Ansicht aufgeblasen ist. __ Sie können onFinishInflate überschreiben.

2
Shaw

Ich hatte das gleiche Problem. Ich habe eine Drittanbieter-Bibliothek verwendet, mit der Sie ihren Adapter für eine GridView überschreiben und Ihr eigenes Layout für jede GridView-Zelle angeben können.

Endlich wurde mir klar, was los war. Eclipse verwendete immer noch die Layout-XML-Datei der Bibliothek für jede Zelle in der GridView, obwohl dies nicht angezeigt wurde. In meinem benutzerdefinierten Adapter wurde angegeben, dass die XML-Ressource aus meinem eigenen Projekt verwendet wurde, obwohl dies zur Laufzeit nicht der Fall war.

Ich habe also sichergestellt, dass sich meine benutzerdefinierten XML-Layouts und -IDs von denen in der Bibliothek unterscheiden, das Projekt gesäubert und dann die richtigen benutzerdefinierten Layouts in meinem Projekt gelesen haben.

Seien Sie vorsichtig, wenn Sie den Adapter einer Drittanbieter-Bibliothek überschreiben und Ihre eigene Layout-XML angeben, die der Adapter verwenden soll. Wenn Ihr Layout in Ihrem Projekt den gleichen Dateinamen wie das in der Bibliothek hat, kann ein wirklich schwer zu findender Fehler auftreten!

2
JDJ

Zusätzlich zu den oben genannten Lösungen stellen Sie sicher, dass
tools:context=".TakeMultipleImages"im Layout ist derselbe Wert in der Datei mainfest.xml:
Android:name=".TakeMultipleImages" für dasselbe Aktivitätselement . Es tritt auf, wenn mit copy and paste eine neue Aktivität erstellt wird

2
user2982286

Ich habe alles ausprobiert, aber nichts hat funktioniert. Also musste ich meine ImageView-Statik public static ImageView texture; und dann texture = (ImageView) findViewById(R.id.texture_back); machen. Ich denke nicht, dass es ein guter Ansatz ist. 

1
Tabish

In meinem Fall hatte ich das Layout aufgeblasen, aber die untergeordneten Ansichten gaben null zurück. Ursprünglich hatte ich folgendes:

@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);
    ...
}

Als ich jedoch Folgendes geändert habe, hat es funktioniert:

@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);
    ...
}

Der Schlüssel bestand darin, das bereits aufgeblähte Layout gezielt zu referenzieren, um die untergeordneten Ansichten zu erhalten. Das heißt, footerView hinzufügen:

  • footerView . findViewById ...
1
Suragch

In meinem Fall gab findViewById null zurück, wenn ich den Aufruf von einem übergeordneten Objekt in ein vom übergeordneten instanziierten Adapterobjekt verschob. Nachdem ich die hier aufgeführten Tricks ohne Erfolg versucht hatte, verschob ich die findViewById wieder in das übergeordnete Objekt und übergab das Ergebnis als Parameter während der Instantiierung des Adapterobjekts. Zum Beispiel habe ich dies in einem übergeordneten Objekt gemacht:

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

Dann habe ich den hdSpinner als Parameter bei der Erstellung des Adapterobjekts übergeben:

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

Mein Fix war, das Projekt einfach zu reinigen. 

0
Liangjun

findViewById kann auch null zurückgeben, wenn Sie sich in einem Fragment befinden. Wie hier beschrieben: findViewById in Fragment

Sie sollten getView () aufrufen, um die oberste Ansicht innerhalb eines Fragments zurückzugeben. Dann finden Sie die Layoutelemente (Schaltflächen, Textansichten usw.).

0
technocrat

Nach meiner Erfahrung scheint dies auch der Fall zu sein, wenn Ihr Code nach OnDestroyView aufgerufen wird (wenn sich das Fragment auf dem Back-Stack befindet.) Wenn Sie die Benutzeroberfläche mit der Eingabe eines BroadCastReceiver aktualisieren, sollten Sie überprüfen, ob dies der Fall ist .

0
Tad

DAS LAYOUT AUFFLASCHEN !! (welche die id enthält)

In meinem Fall hat findViewById () null zurückgegeben, weil das Layout, in dem das Element geschrieben wurde, nicht aufgeblasen wurde ...

ZB . Fragment_layout.xml

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

findViewById (R.id.listview) gab null zurück, da ich nicht getan hatte inflater.inflate (R.layout.fragment_layout, ..., ...); bevor.

Hoffe, diese Antwort hilft einigen von euch.

0
Akshayraj Kore

Es stürzte für mich ab, weil eines der Felder in meiner Aktivitäts-ID mit der ID in einer anderen Aktivität übereinstimmte. Ich habe es mit einer eindeutigen ID behoben.

In meiner loginActivity.xml-Kennwortfeld-ID war "Kennwort" angegeben. In meiner Registrierungsaktivität habe ich es einfach korrigiert, indem ich die ID r_password angegeben habe. Dann wurde kein Objekt zurückgegeben:

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

Ich hatte ein ähnliches Problem, als ich versuchte, eine benutzerdefinierte Ansicht für eine ListView zu erstellen.

Ich habe es einfach so gelöst:

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
Rafael Costa