Навигационный ящик onNavigationDrawerItemSelected вызывается перед MainActivity onCreate?

Я настроил новый проект с реализацией шаблона фрагмента навигационного ящика и MainActivity.

Он предоставляет мне следующие соответствующие методы:

@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));
}

Моя MainActivity запускается активностью-заставкой, которая получает сохраненный токен доступа через EXTRA_TOKEN.

Это переопределение прослушивателя выбора элемента Navigation Drawer в 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;
    }
}

Он запускает три разных фрагмента в зависимости от того, какой элемент выбран в NavDrawer. При создании новых фрагментов строка token передается в его конструктор, который сохраняется в классе фрагмента для дальнейшего использования.

Однако при первом запуске приложения кажется, что onNavigationDrawerItemSelected вызывается перед onCreate! Это приводит к тому, что я передаю токен с нулевым значением во фрагменты, в результате чего они все перепутались.

Как это возможно? Насколько я понимаю, NavigationDrawerFragment еще не должен был быть настроен!

Я установил точки останова как на onCreate, так и на onNavigationDrawerItemSelected switch position = 0. onNavigationDrawerItemSelected действительно был поражен до onCreate.

Как я могу убедиться, что сначала получил токен, прежде чем пытаться обработать onNavigationDrawerItemSelected?

Любая помощь будет оценена по достоинству.


person l3utterfly    schedule 21.05.2014    source источник


Ответы (4)


Я считаю, что понял это, поскольку это происходило со мной для любого, кто ищет это и не может найти ответ.

Если вы используете Android Studio DrawerActivity, то для вас создается шаблонный код. В этом коде в файле activity_main.xml или любом другом XML, который ваша DrawerActivity устанавливает в качестве своего представления содержимого, есть тег.

Когда setContentView() вызывается в onCreate(), этот фрагмент создается автоматически, поэтому технически onCreate() по-прежнему вызывается первым, но затем метод onNavigationDrawerItemSelected() вызывается перед чем-либо еще в create. Поскольку setContentView обычно хранится наверху, это вызывает проблемы при попытке сохранить состояние фрагментов в вашем ящике.

Просто переместите любой код, который проверяет наличие saveInstanceBundle, над setContentView(), и это решит проблему.

Пример с комментариями:

@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));

}
person Eric    schedule 07.11.2014

Вы можете переместить намерение в конструктор и сохранить там свои токены следующим образом:

Intent i;

......

public FragmentConstructor() {

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

}
person AndyRoid    schedule 21.05.2014
comment
Помогите, например, если у намерения.method() есть параметр Context. Когда есть параметр Context, методintent.method(context) получает нулевой контекст. - person damat-perdigannat; 28.10.2014

Что мне нужно было сделать, чтобы заставить его работать, так это проверить, загрузилась ли страница перед выполнением 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;
    }
person abinop    schedule 18.06.2015

Я также согласен с использованием логического значения для проверки завершения загрузки onCreate(). Мои единственные другие предложения заключаются в том, что для быстрого исправления вы можете использовать onSectionAttached(int number) для обработки каждого выбранного элемента вместо onNavigationDrawerItemSelected.

person codebyjames    schedule 09.09.2015