Recyclerview -> getChildAt() liefert null

  • Antworten:6
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 53

20.09.2017, 16:01:29 via Website

Hallo,

ich hab schon wieder eine Frage:)
Ich habe in einer Fragment-Klasse folgendes in der OnViewCreated-Funktion stehen:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
{
    mainRecyclerView = (RecyclerView) view.findViewById(R.id.fragmentAddElementRecyclerView);
    mainLayoutManager = new LinearLayoutManager(getActivity());
    mainRecyclerView.setLayoutManager(mainLayoutManager);

    mainAdapter = new RVAdapter(getActivity());
    mainRecyclerView.setAdapter(mainAdapter);

    if(MainActivity.DARK_THEME)
        tmpManageDesign.changeTheme(true, getActivity(), view);
    else
        tmpManageDesign.changeTheme(false, getActivity(), view);

    super.onViewCreated(view, savedInstanceState);
}

In der Klasse ManageDesign sieht die Funktion changeTheme wie folgt aus:

RecyclerView tmpRecyclerView = (RecyclerView) fragmentView.findViewById(R.id.fragmentAddElementRecyclerView);
RecyclerView.Adapter tmpAdapter = tmpRecyclerView.getAdapter();

for(int i=0; i<tmpAdapter.getItemCount(); i++)
{
Log.d("AUS ::: ", "COUNT = " + Integer.toString(tmpAdapter.getItemCount()));
View curView = tmpRecyclerView.getChildAt(i);

ImageView tmpItemImageMain = (ImageView) curView.findViewById(R.id.itemImageMain);
...
}

"fragmentAddElementRecyclerView" ist die RecyclerView.
"fragmentview" ist die übergebene View von changeTheme(...).

Jetzt ist es so, das "tmpRecyclerView" die Recyclerview enthält, "getItemCount()" auch die richtige Anzahl (7) ausgibt, aber die Zeile

View curView = tmpRecyclerView.getChildAt(i);

Immer mit Null fehlschlägt. Ich weiss nicht weiter.

Ich erhalte immer:
Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
zur folgenden Zeile:

ImageView tmpItemImageMain = (ImageView) curView.findViewById(R.id.itemImageMain);

curView ist also immer Null, aber ich weiss einfach nicht, woran es liegt.

Kann mir jemand bitte sagen, was hier falsch ist?

— geändert am 20.09.2017, 16:04:34

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

20.09.2017, 16:29:32 via Website

Hallo next user,
ich würde mal vermuten, dass Android zu dem Zeitpunkt zu dem du das Theme ändern willst, noch keine ChildViews erstellt hat.
Der ItemCount ist immer die anzahl der Items deiner Auflistung, aber es werden ja nicht alle Items als Views "berechnet" und angezeigt, das macht das System ja erst, wenn man die Views wirklich braucht.
D.h. für deine Schleife darfst du nicht das ItemCount nehmen sondern RecyclerView#getChildCount() und das wird an der stelle immer 0 sein. (https://stackoverflow.com/questions/38147000/recyclerview-getchildcount-is-returning-different-number-of-child-everytime)

Ich nehme an, du willst das Theme der ChildViews anpassen, und das theme ist in einer Einstellung o.ä. festgelegt.

Ich mache das ganze in der GetView/onBindViewHolder vom Adapter, denn getView/onBindViewHolder wird immer dann aufgerufen, wenn dass entsprechende Item geladen wird. Darin kannst du dann genau das Theme des geladenen Items setzen und es wirkt sich für alle aus.

Angenommen deine akutelle Methode würde funktionieren, würde sie immer nur alle sichtbaren Items der Liste verändern, sobald du jedoch scrollst, müsstest du alles aktualisieren und das ist wenig sinnvoll..

Also am besten im Adapter in onBindViewHolder init das ganze Theme gedöns durchführen.

— geändert am 20.09.2017, 16:30:20

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 53

20.09.2017, 17:12:10 via Website

Hallo Pascal.

Ich habe in der MainActivity einene leeren "Container", in den ich verschiedene Fragmente lade. Das Startfragment hat einen Button, welcher beim drücken ein anderes Fragment (nähmlich das mit der Recyclerview) in den Container setzt.
Das klappt auch alles.

Jetzt sollen aber noch gewisse Dinge (Textfarbe, Icon, ect...) der Items geändert werden, je nachdem, ob DARK_THEME true oder false ist. Das mache ich in der Klasse ManageDesign in der Funktion changeTheme (zumindest habe ich es vor).

Wenn ich dich richtig verstanden habe, so werden die Items und die Recyclerview im Code in der onViewCreated gesetzt, aber sind für die Funktion changeTheme (welche direkt danach aufgerufen wird) noch nicht sichtbar.

Ab welchen Status beim setzen des Fragments sind diese denn sichtbar?

Wie gesagt, beim Klick auf den Button im Startfragment, wird dieses sofort mit dem Recyclerview-Fragment ersetzt und die Items angezeigt. Diese sollen jetzt aber im Design angepasst werden, also "beim setzen des Fragments".

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

20.09.2017, 17:22:38 via Website

Richtig, soll beim setzen des Fragments passieren, aber das kann in diesem Fall nicht dein Trigger für diese Aktion sein.
Beispiel:

AppStart -> Button Klick -> Fragment init (und wird angezeigt)

Gleichzeitig mit dem Fragment init wird deine RecyclerView mit den zugehörigen Daten initialisiert.
DIese initialisierung bewirkt, dass die Items als Views dargestellt werden. Die einzelen ChildViews werden dann über onBindViewHolder initialisiert und angezeigt.

Bedeutet vereinfacht:
Beim Anzeigen des Fragments wird indirekt auch onBindViewHolder vom Recyclerview aufgerufen, in welcher du dann deine Designänderungen tun kannst.

Du kannst natürlich auch deine Möglichkeit nehmen und warten bis alles erstellt wurde, d.h. deine Methode nach der onCreate aufrufen, z.b. in der OnResume oder per Handler Zeitesteuert. Dies ist aber alles deutlich ineffizienter, da du wie gesagt bei jedem Scroll alle Items erneut abändern müsstest. Wenn du die anpassung in der onBindViewHolder programmierst, dann wird auch beim scrollen neue sichtbare Items aufs passende Design gebracht.

— geändert am 20.09.2017, 17:23:07

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
  • Forum-Beiträge: 53

20.09.2017, 17:40:58 via Website

onBindViewHolder hatte ich vergessen. Hatte die ganze Zeit vergessen, das die Items ja im Adapter "richtig" Zusammengesetzt werden und ich sie dort direkt "formen kann".

Werd es mal später umsetzen und schauen, muss jetz weg.
Vielen dank schonmal für die schnellen Antworten.

Antworten
  • Forum-Beiträge: 53

24.09.2017, 17:03:57 via Website

Gut, diese Sache wäre geklärt. Habe es jetzt im nachhinein auch besser verstanden, als ich den Code nochmal gründlicher durchgegangen bin...

Vielen dank Pascal.

— geändert am 24.09.2017, 17:25:57

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.177

24.09.2017, 17:59:53 via App

Hallo next!
Super, wenn deine Frage geklärt ist, setze doch bitte noch deinen Thread auf "Beantwortet"!

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten

Empfohlene Artikel