0

Je ne sais pas comment utiliser findViewById(R.id.nav_timetable); sans qu'il retourne null et créer un NPE. Ce que j'essaie de faire est de faire en sorte que le TimetableFragment soit chargé par défaut et que les gens puissent utiliser le tiroir pour aller à d'autres fragments.Comment utiliser findViewById() dans onCreate sans qu'il renvoie null?

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

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
    setSupportActionBar(toolbar); 

    setupDrawer(toolbar); 

    drawer.openDrawer(GravityCompat.START); // Opened this on first run so they know what's in it. 

    // TODO Change this later to a home page and remove goToTimetablePage(); 
    // goToTimetablePage(); 
    goToFragmentFromNavMenuItem((MenuItem) findViewById(R.id.nav_timetable)); 
} 

@Override 
public boolean onNavigationItemSelected(MenuItem menuItem) { 
    // Handle navigation view item clicks here. 

    goToFragmentFromNavMenuItem(menuItem); 
    return true; 
} 

private void goToFragmentFromNavMenuItem(MenuItem menuItem) { 
    // Create a new fragment and specify the fragment to show based on nav item clicked 
    Fragment fragment = null; 
    Class fragmentClass; 

    switch (menuItem.getItemId()) { 
     case R.id.nav_slideshow: // TODO fragmentClass = SlideshowFragment.class; break; 
     case R.id.nav_share: // TODO fragmentClass = ShareFragment.class; break; 
     case R.id.nav_timetable: 
      fragmentClass = TimetableFragment.class; 
      // goToTimetablePage(); 
      break; 
     default: 
      fragmentClass = TimetableFragment.class; 
      // TODO Change this later to a home page: 
      // TODO fragmentClass = HomeFragment.class; Remove "goToTimetablePage();" 
    } 


    //noinspection TryWithIdenticalCatches 
    try { 
     fragment = (Fragment) fragmentClass.newInstance(); 
    } catch (InstantiationException e) { 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } 

    FragmentManager fragmentManager = getSupportFragmentManager(); 

    fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit(); 

    menuItem.setChecked(true); 
    setTitle(menuItem.getTitle()); 
    drawer.closeDrawer(GravityCompat.START); 
} 

Message d'erreur:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.gmail.gogobebe2.thedayahead/com.gmail.gogobebe2.thedayahead.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'int android.view.MenuItem.getItemId()' on a null object reference 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
    at android.app.ActivityThread.-wrap11(ActivityThread.java) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:148) 
    at android.app.ActivityThread.main(ActivityThread.java:5417) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
    Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int android.view.MenuItem.getItemId()' on a null object reference 
    at com.gmail.gogobebe2.thedayahead.MainActivity.goToNavFragment(MainActivity.java:123) 
    at com.gmail.gogobebe2.thedayahead.MainActivity.onCreate(MainActivity.java:59) 
    at android.app.Activity.performCreate(Activity.java:6237) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)  
    at android.app.ActivityThread.-wrap11(ActivityThread.java)  
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)  
    at android.os.Handler.dispatchMessage(Handler.java:102)  
    at android.os.Looper.loop(Looper.java:148)  
    at android.app.ActivityThread.main(ActivityThread.java:5417)  
    at java.lang.reflect.Method.invoke(Native Method)  
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)  
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)  

J'essayé d'utiliser la méthode onCreateView mais il vient de faire des messages stackoverflow pour une raison quelconque.

EDIT: Voici tout le code pour effacer toute confusion: https://github.com/gogobebe2/TheDayAhead

EDIT2: Assurez-vous que vous ne vous inquiétez pas au sujet de la méthode goToTimetablePage(). Il est inutilisé pour le moment et je prévois de le déplacer vers le fragment TimetableFragment.

EDIT3: J'ai changé le nom de la méthode en goToFragmentFromNavMenuItem() pour mieux décrire ses actions pour éclaircir les choses. Je veux aussi que vous sachiez que la méthode onNavigationItemSelected(MenuItem menuItem) fonctionne parfaitement avec la méthode goToFragmentFromNavMenuItem(), c'est juste que ça ne fonctionne pas quand elle est utilisée à l'intérieur onCreate(Bundle savedInstanceState) à cause du findViewById(R.id.nav_timetable) retournant null tout le temps.

En outre, ceci est ma première application Android que j'ai jamais faite et j'apprends un peu comme je le fais. Je ne savais même pas quels fragments étaient la nuit dernière, donc je suis vraiment nouveau sur Android, s'il vous plaît n'assumez aucune connaissance.

+0

poster votre R.layout.activity_main –

Répondre

1

Pour éviter l'accident en raison de la NPE vous pouvez tester la valeur retournée être différente par null avant de le passer:

MenuItem menuItem = (MenuItem) findViewById(R.id.nav_timetable); 
if (menuItem != null) { 
    goToNavFragment(menuItem); 
} 

Quoi qu'il en soit, cela ne résoudra pas votre problème, en fait findViewById(int) est de retour null car l'ID de vue que vous recherchez n'existe pas dans votre présentation d'activité.

La méthode findViewById(), qui vient de la classe View et vous invoquez sur this qui est un Activity (une classe qui étend View), recherche un identifiant de vue (de R) à l'intérieur de la mise en page actuellement gonflé. Maintenant, si vous jetez un coup d'oeil à votre implémentation onCreate, vous voyez que vous appelez le setContentViewMethod(R.layout.activity_main); cela signifie que vous définissez la mise en forme de cette activité en la prenant à partir de la mise en page xml avec l'ID activity_main.

Le gros problème ici est que la mise en page que vous transmettez (activity_main) ne contient pas l'identifiant que vous recherchez. Jetez un coup d'oeil au fichier de disposition activity_main.xml, comme vous pouvez le voir il n'y a aucun objet avec l'ID R.id.nav_timetable.

Une activité ne peut avoir qu'un seul fichier d'activité de mise en page chargé en même temps. Vous pouvez toujours charger d'autres fichiers de disposition pour des menus ou des objets de vue particuliers (Spinner s, List s, etc.).

La chose la plus importante ici est que vous essayez de récupérer un MenuItem; pour y parvenir, vous devez remplacer deux méthodes onCreateOptionsMenu() et onOptionsItemSelected().Le onCreateOptionsMenu() fait ce que son nom l'indique. Il crée le menu d'options que vous allez utiliser. Ici, vous pouvez accrocher vos actions, mais la chose la plus importante que vous devez faire est de gonfler une disposition de menu. Sans cela, vous ne pourrez pas appliquer une disposition de menu personnalisée et utiliser findViewById.

Par conséquent, avant d'appeler le findViewById(), vous devriez faire comme:

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.your_menu_id, menu); 

    // findViewById() 

    return true; 
} 

Le onOptionsItemSelected() sera appelé lorsqu'un élément de votre menu précédemment créé est sélectionné, il vous donnera un argument sélectionné MenuItem et ici vous pouvez implémenter l'élément de menu cliquez sur actions. Une implémentation standard peut être la suivante:

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
     case R.id.action_one: 
      doSomething() 
      return true; 
     case R.id.action_two: 
      doSomethingElse(); 
      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
    } 
} 
+0

Je travaille dans l'activité principale. Vérifiez l'édition de la question pour le code complet. Je vais tester rapidement avec la méthode onFinishInflate() maintenant et je reviendrai vers vous. – gogobebe2

+0

Apparemment, "onFinishInflate()" n'est pas une méthode à remplacer dans une activité. – gogobebe2

+0

Oui, parce que c'est une méthode Fragment, je pensais que vous travailliez à l'intérieur d'un fragment. – FredMaggiowski

0

La façon de ne pas retourner null est de lui passer un Id valide pour la vue. Regardez dans votre fichier de conception XML et utiliser l'identifiant dans votre fonction comme ceci:

rootview.findViewById(R.id.your_id_here)

+0

J'ai utilisé un identifiant valide. Jetez un oeil à la modification pour le code complet. – gogobebe2

+0

S'il vous plaît regarder les modifications que j'ai apportées à ma question, merci :) – gogobebe2

0

Étant donné que votre question ne comprend pas les fichiers mise en page Je suppose que R.id.nav_timetable fait référence à fragment ID de » (et que il est partie de votre mise en page)? Si oui, vous devez utiliser findFragmentById() de FragmentManager (ou SupportFragmentManager) au lieu de findViewById().

+0

R.id.nav_timetable se réfère à l'élément Menu dans le tiroir. – gogobebe2

+0

S'il vous plaît regardez les modifications que j'ai apportées à ma question, merci :) – gogobebe2