Unklarheit beim nachladen eines Submenus

  • Antworten:13
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 178

24.03.2021, 21:34:34 via Website

Hallo Leute!

Ich bin gerade am optimieren einer Activity. Ich versuche gerade ein SUbmenu so zu gestalten, das diese sich wie Ordner verhalten, soll heissen ich klicke mich durch SubMenus...:

subMenu.add(1,b,b++,dsPhase.getname()).
     setIcon(R.drawable.gruppen)
     .setVisible(true)
     .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
         @Override
          public boolean onMenuItemClick(MenuItem item) {
                    subMenu.clear();
                   loadPhase(dsPhase);
                  }
                   return true;
                  }
          });

In loadPhase(dsPhase) soll nun das darunterliegende SUbMenü geladen werden. laut logs wird alles aufgerufen aber der angeklickte subMenu verschwindet nicht, und die neuen werden nicht geladen....
( wenn nur ein ordner vorhanden ist, wird automatisch auf das nächste verzeichnis verwissen ( auch loadPhase(dsPhase) ) und es klappt! )

wenn ich nun
subMenu.clear();
loadPhase(dsPhase);

in firebase addListenerForSingleValueEvent lade, funktioniert es aber auch:

subMenu.add(1,b,b++,dsPhase.getname()).
          setIcon(R.drawable.gruppen)
          .setVisible(true)
          .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
         @Override
            public boolean onMenuItemClick(MenuItem item) {
               dsPhase.getDataSnapshot().getRef().addListenerForSingleValueEvent(new ValueEventListener() {
              @Override
                  public void onDataChange(@NonNull DataSnapshot snapshot) {
                       subMenu.clear();
                      loadPhase(dsPhase);
                      }
                  @Override
                    public void onCancelled(@NonNull DatabaseError error) { }
                   });
              return true;
          }
     });

da ich aber am Optimieren bin, und die Daten ja schon habe, und den Datasnapshot mit(dsPhase) weitergeben möchte, will ich keine Call funktion mehr aufrufen, wie kann ich den erneuten aufruf umgehen, woran liegt überhaupt das Problem? ich habe auch ein a.runonUiThread versucht, ich kapiers nicht! VIelen dank schon mal in vorraus

Diskutiere mit!
  • Forum-Beiträge: 178

25.03.2021, 19:06:51 via Website

Also ich bin weiterhin für vorschläge offen.... was auch funktioniert ist :

new Thread(new Runnable() {
                                            @Override
                                            public void run() {
                                                a.runOnUiThread(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        subMenu.clear();
                                                        loadPhase(dsPhase);
                                                    }
                                                });

                                            }
                                        }).start();

Aber in ernst... das kanns doch nicht sein?

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.421

25.03.2021, 20:58:52 via Website

Hallo

Aber in ernst... das kanns doch nicht sein?

Wieso kann das nicht sein?
Wenn du in einem anderen Thread bist als dem UI ist das ja normal. Du willst eine Ausgabe Veränderung auf dem Bildschirm machen und das geht nur im UI.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 11.158

25.03.2021, 21:07:17 via App

Warum machst du denn überhaupt einen neuen Thread?
ist das in deinem Beispiel nicht überflüssig?

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

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.421

25.03.2021, 21:15:15 via Website

@Pascal das hat mich auch gewundert.
Auch warum er da "a." benutzt.
Context falsch?

Fehlermeldung die bestimmt kommen sehen wir nicht.

— geändert am 25.03.2021, 21:29:15

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 178

26.03.2021, 06:45:40 via Website

Aber genau das mein ich ja, ich muss zuerst einen neuen Thread starten, und darin einen neuen UI Thread, dann lädt es das menü nach, ansonsten passiert nichts, obwohl alles ausgeführt wird laut den Logs.
Im a. ist einfach die activity die ich so z.t. auf andere classen übergebe für den Context oder evtl aufrufe neuer Activitys....

Jedenfalls, Vorher hatte ich immer den Firebase aufruf drin, da funktioniert es auch, es hat stunden gedauert bis ich herausfand das es daran lag.

Und das ist nur im itemonclicklistener, wenn die function beim start aufgerufen wird, wird es auch ausgeführt

— geändert am 26.03.2021, 06:53:25

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.421

26.03.2021, 08:25:38 via Website

Eine Frage wovon erbt deine Klasse in der du bist?

Das du den Context der Activity brauchst sollte klar sein. Also versuche mal a.subMenu.clear();

Wichtig ist aber auch wir du die variable subMenue initialisiert hast ob sie auch auf das Menü on der Activity zeigt.

Wahrscheinlich gibst es in der Klasse von der du erbst auch die Methode.
SubMenue erbt von Menue. Deshalb bekommst du keinen Kompiler Fehler.
Aber der Aufruf geht trosdem ins lehre.
Da falscher Context.

PS wenn du den extra Thread brauchst bist du wohl doch im UI. Also Context. Du bist ja in einer callback Methode.

— geändert am 26.03.2021, 12:08:15

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 178

26.03.2021, 19:39:04 via Website

Also das submenu lade ich aus der Klasse heraus, also nicht in einer funktion. ich habe a.subMenu.clear(); versucht, das klappt aber nicht dahher habe ich submenu nachher auf static gesetzt und mit Turnier_Overview.subMenu.clear(); versucht..

Ich hatte während der Arbeit viele gedanken und Theorien die ich ebenfalls durch gegangen bin und jetzt versucht habe....
- Wenn ich es in der funktion deklariere als mit final SubMenu submenu ( funktioniert es nicht)
- Habe es als private static Submenu in der Klasse, Turnier_Overview.subMenu.clear(); probiert.... funktioniert ebenfalls nicht.
-Ich habe onPrepareOptionsMenu(menu/submenu) und onCreateOptionsMenu(menu/submenu) jeweils mit dem menu und submenu gefüllt ( davor und danach) , funktioniert nicht.

Es gibt zwei möglichkeiten... entweder funktioniert es wirklich nicht, oder ich habe irgendwo, etwas eingestellt wo das ganze verhindert. Den sobald ich es in den new Thread/a.runOnUiThread setzte funktioniert es einwandfrei.

Ich versuch es weiter, aufgeben is nicht! ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 178

26.03.2021, 19:58:40 via Website

ALso an der Java Klasse sollte kein fehler drin sein... habe mir eine neue kurze Klasse geschrieben und es funktioniert wirklich nur wenn ich es über diesen Thread/UiThread versuche: (Auf dem Tablet und auf BlueStacks.....)

package com.awad.scoreboard.openTournament;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.drawerlayout.widget.DrawerLayout;

import com.awad.scoreboard.dartturnier.R;
import com.awad.scoreboard.openTournament.helperclasses.Logs;
import com.google.android.material.navigation.NavigationView;

public class SubmenuTest extends Activity {

private View v;
private DrawerLayout drawerLayout;
private Menu menu;
private SubMenu submenu;
private Logs logs = new Logs("SubMenuTest");
private Activity a;


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    a = this;
    v= LayoutInflater.from(this).inflate(R.layout.turnier_overview_layout,null);
    drawerLayout = v.findViewById(R.id.drawer_layout);
    setContentView(v);
    final NavigationView navView = (NavigationView) findViewById(R.id.nav_view);
    menu = navView.getMenu();
    submenu = menu.addSubMenu("ratata");
    submenu.add("blabala").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                    a.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            logs.i("sollte");
                            submenu.clear();
                            submenu.add("blabla2");
                        }
                    });
                }
            }).start();


            return false;
        }
    });
}

}

hier meine xmls
DrawerLayout

xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <include
        layout="@layout/game_overview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <Button
        android:id="@+id/menu_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:background="@drawable/game_background_button"

        android:rotation="270"
        android:text="@string/menu" />
</RelativeLayout>


<com.google.android.material.navigation.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/menu_header"
   app:menu="@menu/turnier_overview_menu">



</com.google.android.material.navigation.NavigationView>

und Menu:

<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" android:layout_width="match_parent" android:id="@+id/menu_overview">
<group android:id="@+id/turnier_overview">
    <item
        android:id="@+id/nav_item_one"
        android:title="Aktive Spiele" />
    <item
        android:id="@+id/nav_item_two"
        android:title="Offene Spiele"/>
    <item
        android:id="@+id/nav_item_three"
        android:title="Beendete Spiele" />
    <item
        android:id="@+id/nav_pdf"
        android:title="PDF Generieren" />
</group>

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.421

26.03.2021, 20:27:56 via Website

Also als erstes finde ich es unüblich wie du dein Layout lädst.
Dein drawerlayout suchst du vor dem setcontentview. Ob du da die richtige ID bekommst fragwürdig.

Frage welcher von den beiden Menüs wird den angezeigt blabla oder blabala2?
Wird dein ratata angezeigt?

— geändert am 26.03.2021, 21:03:20

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 178

26.03.2021, 22:34:29 via Website

Also ratata wird geladen, so auch das blabla. Wenn ich auf blabla clicke und das newThread/ runonui thread drin habe, lädt es auch das blabla2 und nlabla wird entfernt. Sonst nicht.
Das mit der reihenfolge von setcontenview und des drawlayout habe ich gar nicht beachtet, habe den script in der schnelle geschrieben, aber es funktioniert. Da ich gerade nicht zuhause bin kann ich es andersrum gerade nicht probieren, ich bin aber sicher das ich in der anderen Klasse zuerst das contentview lade.

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.421

27.03.2021, 12:54:05 via Website

Hallo
Eigentlich benutzt du auch den falschen Listener für dein NavDrawer.
OnMenuItemClickListener ist für das Menü in der Actionbar.

NavigationView Implementirt den OnNavigationItemSelectedListener.
https://developer.android.com/reference/com/google/android/material/navigation/NavigationView

Da bekommst du auch den richtigen Menüeintrag in der Methode mitgeliefert auf den geklickt wird.
Für mich ist es auch nicht so sinnvoll das “submenu“ zulöschen denn das zeigt ja auf dein "ratata"submenu , und dann in das leere Menü einen neuen Eintrag (Item) zusetzen. „submenu.add“.

PS.
Da deine Variablen private sind sollte der zugriff im Listener Callback Methode so aus sehen.

SubmenuTest.this.submenu.clear();

— geändert am 27.03.2021, 13:34:39

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 178

27.03.2021, 18:16:25 via Website

hmmmm... stimmt,ich erinnere mich, habe ich so zu beginn versucht, und war nicht sonderlich begeistert da ich jeweils die Ids setzten musste und über umwege den DataSnapshot neu holen.
Da Die ItemIds Integer sind, aber die Ids von FIrebase sind strings, hab ich es deshalb verworfen.
und habe auf den setOnMenuItemClickListener gewechselt. da ich den DataSnapshot gleich weitergeben konnte. was auch wunderbar funktioniert hat, bis zu dem Zeitpunkt wo ich den Snapshot noch vom Server holte... :)

Ich versuch mich nochmal mit OnNavigationItemSelectedListener ausseinanderzusetzten, und mit Switch/case etwas sinvolles zu zimmern. ANsonsten ist es halt so, dan mach ich den kleinen Umweg , bin einfach extrem verwundert das es so funktioniert, direkt aber nicht.

Und public und private hatte eigentlich keinen einfluss, hab ich auch mal gewechselt....

— geändert am 27.03.2021, 18:17:42

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.421

27.03.2021, 19:56:18 via Website

Solange du in dem Listener bist kannst du das Menu nicht ändern oder löschen.
Da du einen Thread startest. Beendest du auch den Listener der Thread macht dann danach deine Änderung. Eigentlich ein normales verhalten.

— geändert am 27.03.2021, 19:56:55

Hilfreich?
Diskutiere mit!