0

Я не знаю, как использовать findViewById(R.id.nav_timetable); без его возврата null и создания NPE. Я пытаюсь сделать загрузку TimetableFragment по умолчанию, и тогда люди могут использовать ящик для перехода к другим фрагментам.Как использовать findViewById() в onCreate без его возврата 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); 
} 

Сообщение об ошибке:

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)  

Я попытался с помощью метода onCreateView но это только что сделал StackOverflow сообщения по какой-то причине.

EDIT: Вот весь код, чтобы прояснить путаницу: https://github.com/gogobebe2/TheDayAhead

EDIT2: Убедитесь, что вы не беспокойтесь о методе goToTimetablePage(). В настоящий момент он не используется, и я планирую переместить его в фрагмент TimetableFragment.

EDIT3: Я изменил имя метода на goToFragmentFromNavMenuItem(), чтобы оно лучше описывало его действия по очистке. Я также хочу, чтобы вы, ребята, знали, что метод onNavigationItemSelected(MenuItem menuItem) отлично работает с методом goToFragmentFromNavMenuItem(), просто он не работает, когда используется внутри onCreate(Bundle savedInstanceState) из-за findViewById(R.id.nav_timetable), возвращающего null все время.

Кроме того, это мое первое приложение для Android, которое я когда-либо делал, и я как бы получаю удовольствие от обучения. Я даже не знал, какие фрагменты были прошлой ночью, поэтому я действительно новичок в Android, пожалуйста, не знайте никаких знаний.

+0

Опубликовать свой R.layout.activity_main –

ответ

1

Чтобы избежать аварии из-за NPE вы можете проверить возвращаемое значение будет отличаться нулем перед передачей:

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

Во всяком случае, это не решит проблему, на самом деле findViewById(int) возвращается null, поскольку идентификатор вида, который вы ищете, не существует в вашем макете активности.

Метод findViewById(), который исходит из View класса и вы вызываете его на this который является Activity (класса, который расширяет View), ищет вид идентификатора (от R) внутри текущего завышены макета.

Теперь, если вы посмотрите на свою реализацию onCreate, вы увидите, что вы вызываете setContentViewMethod(R.layout.activity_main); это означает, что вы устанавливаете макет этого активности, взяв его из макета xml с идентификатором activity_main.

Большая проблема заключается в том, что макет, который вы передаете (activity_main), не содержит идентификатор, который вы ищете. Просто взгляните на файл макета activity_main.xml, так как вы можете видеть, что нет объекта с идентификатором R.id.nav_timetable.

Активность может содержать только один файл активности макета, загружаемый одновременно. Вы можете загрузить другие файлы макетов для меню или отдельных объектов вида (Spinner s, List и т. Д.).

Самое главное здесь, что вы пытаетесь получить MenuItem; для этого вам необходимо переопределить два метода: onCreateOptionsMenu() и onOptionsItemSelected().


onCreateOptionsMenu() выполняет свое название. Он создает меню опций, которое вы собираетесь использовать. Здесь вы можете подключить свои действия, но самое главное, что вы ДОЛЖНЫ сделать, - раздуть макет меню. Без этого вы не сможете применить пользовательский макет меню и использовать findViewById.

Следовательно, перед вызовом findViewById() вы должны сделать так:

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

    // findViewById() 

    return true; 
} 

onOptionsItemSelected() будет вызываться при выборе элемента из ранее созданного меню, это даст вам в качестве аргумента выбранного MenuItem и здесь вы можете реализовать действия щелчка элемента меню. Стандартная реализация может быть следующим:

@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

Я работаю в основном мероприятии. Проверьте редактирование вопроса для полного кода. Я быстро протестирую метод onFinishInflate() прямо сейчас и вернусь к вам. – gogobebe2

+0

Очевидно, что «onFinishInflate()» - это не метод, который можно переопределить в Activity. – gogobebe2

+0

Да, потому что это метод Фрагмента, я думал, что вы работаете внутри фрагмента. – FredMaggiowski

0

Путь для этого не возвращать нуль, чтобы передать его действительное удостоверение личности для представления. Посмотрите в вашем дизайне файл XML и использовать идентификатор в вашей функции, как это:

rootview.findViewById(R.id.your_id_here)

+0

Я использовал действительный идентификатор. Посмотрите на редактирование полного кода. – gogobebe2

+0

Пожалуйста, ознакомьтесь с изменениями, внесенными мной на мой вопрос, спасибо :) – gogobebe2

0

Поскольку ваш вопрос не включает раскладку я предполагаю, что R.id.nav_timetable относится к фрагменту ID «s (и что это часть вашего макета)? Если это так, вам необходимо использовать findFragmentById() от FragmentManager (или SupportFragmentManager) вместо findViewById().

+0

R.id.nav_timetable относится к MenuItem в ящике. – gogobebe2

+0

Пожалуйста, посмотрите на изменения, которые я сделал на мой вопрос, спасибо :) – gogobebe2