8

Ho impostato un nuovo progetto con l'implementazione del modello di Navigation Drawer Fragment e MainActivity.Navigation Drawer onNavigationDrawerItemSelected chiamato prima di MainActivity onCreate?

Mi dà i seguenti metodi rilevanti:

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

    Intent intent = getIntent(); 
    token = intent.getStringExtra(EXTRA_TOKEN); 

    mNavigationDrawerFragment = (NavigationDrawerFragment) 
      getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); 
    mNavigationDrawerFragment.activityMain = this; 

    mTitle = getTitle(); 

    // Set up the drawer. 
    mNavigationDrawerFragment.setUp(
      R.id.navigation_drawer, 
      (DrawerLayout) findViewById(R.id.drawer_layout)); 
} 

mio MainActivity viene avviato da un'attività iniziale che ottiene un token di accesso salvato tramite l'EXTRA_TOKEN.

Questa è la sostituzione della navigazione cassetto voce selezionata ascoltatore nella MainAcitivity:

@Override 
public void onNavigationDrawerItemSelected(int position) { 
    // update the main content by replacing fragments 
    FragmentManager fragmentManager = getSupportFragmentManager(); 
    onSectionAttached(position + 1); 

    switch(position) { 
     case 0: 
      fragmentManager.beginTransaction() 
        .replace(R.id.container, FeedFragment.newInstance(token, "")) 
        .commit(); 
      break; 

     case 1: 
      fragmentManager.beginTransaction() 
        .replace(R.id.container, PeopleFragment.newInstance("", "")) 
        .commit(); 
      break; 

     case 2: 
      if(qbloggedin) { 
       fragmentManager.beginTransaction() 
         .replace(R.id.container, MessagesFragment.newInstance(token, "")) 
         .commit(); 
      } 
      break; 

     default: 
      break; 
    } 
} 

inizia tre frammenti differenti a seconda di quale è selezionato elemento nella NavDrawer. Mentre si istanziano i nuovi frammenti, la stringa token viene passata nel suo costruttore, che viene salvato nella classe del frammento per un ulteriore utilizzo.

Al primo avvio, tuttavia, sembra che onNavigationDrawerItemSelected venga chiamato prima dello onCreate! Questo mi ha portato a passare un token di valore nullo nei frammenti, causando loro di essere tutti incasinati.

Com'è possibile? A quanto ho capito, NavigationDrawerFragment non dovrebbe essere stato ancora configurato!

Ho impostato i punti di interruzione su entrambi onCreate e su onNavigationDrawerItemSelected switch position = 0. onNavigationDrawerItemSelected è effettivamente raggiunto prima dello onCreate.

Come posso assicurarmi di ottenere il token prima di provare a gestire lo onNavigationDrawerItemSelected?

Qualsiasi aiuto sarebbe apprezzato.

risposta

1

Si potrebbe spostare l'intento di un costruttore e salvare le gettoni lì in questo modo:

Intent i; 

...... 

public FragmentConstructor() { 

    i = getIntent(); 
    token = intent.getStringExtra(EXTRA_TOKEN); 

} 
+0

Aiuto per favore quando per esempio intent.method() ha un parametro di contesto. Quando c'è un parametro di contesto, intent.method (contesto) ottiene un contesto nullo. –

10

Credo di aver capito questo, come stava accadendo a me per chi cerca questo e non riesce a trovare il risposta.

Se si utilizza Android Studio DrawerActivity, è disponibile un codice che viene creato automaticamente. In questo codice in activity_main.xml o in qualsiasi XML impostato da DrawerActivity come visualizzazione del contenuto, è presente un tag.

Quando viene chiamato setContentView() su onCreate(), questo frammento viene creato automaticamente e quindi tecnicamente onCreate() viene ancora chiamato per primo, ma il metodo onNavigationDrawerItemSelected() viene chiamato prima di qualsiasi altra cosa nella creazione. Dato che setContentView è generalmente mantenuto in alto, questo causa problemi quando si tenta di memorizzare lo stato dei frammenti nel cassetto.

Sposta semplicemente qualsiasi codice che controlli saveInstanceBundle sopra setContentView() e risolverà il problema.

Esempio con i commenti:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // THIS IS WHERE YOU CHECK FOR SAVED INSTANCE 
    // Check for frag 
    if (savedInstanceState != null) { 
     Log.i(TAG, "Get QuestionDayFragment"); 
     mQuestionDaysFragment = (QuestionDaysFragment) getSupportFragmentManager().getFragment(savedInstanceState, QUESTION_DAY_FRAGMENT); 
    } 

    // View injection 
    setContentView(R.layout.activity_main); 
    ButterKnife.inject(this); 

    // THIS IS WHERE THE CODE WAS BEFORE 
    // THIS WOULD BE CALLED AFTER onNavigationDrawerItemSelected() 

    // Singleton injection 
    LifeboxApplication.graph().inject(this); 

    // Toolbar 
    setSupportActionBar(mToolbar); 

    // FB 
    uiHelper = new UiLifecycleHelper(this, callback); 
    uiHelper.onCreate(savedInstanceState); 

    // Drawer 
    mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); 
    mTitle = getTitle(); 
    mNavigationDrawerFragment.setUp(R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout)); 

} 
0

Quello che ho dovuto fare per rendere il lavoro è stato quello di verificare se la pagina è stata caricata prima di eseguire onNavigationDrawerItemSelected

private Boolean loaded=false; 

    protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState);   

      // Your code here 
      this.loaded=true; 
    } 

    public void onNavigationDrawerItemSelected(int position) { 
     if (!this.loaded){ 
      return; 
    } 
0

Sono d'accordo anche con l'utilizzo di un valore booleano a controllare se onCreate() ha terminato il caricamento. I miei unici suggerimenti sono che per una soluzione rapida è possibile utilizzare onSectionAttached (numero int) per elaborare ogni elemento selezionato anziché onNavigationDrawerItemSelected.

Problemi correlati