Активность Android: обрабатывать намерение после onCreate()?

#java #android #android-fragments #android-activity

#java #Android #android-фрагменты #android-активность

Вопрос:

У меня проблема с порядком инициализации моей активности Android.

Основы:

Действие содержит ViewPager, содержащий 3 фрагмента. Активность открывается таким образом:

   Intent foodsActivityIntent = new Intent(getActivity(), FoodsActivity.class);
  foodsActivityIntent.putExtra("NavigationPosition", navigationPosition);
  foodsActivityIntent.putExtra("SearchQuery", searchQuery);
  foodsActivityIntent.putExtra("SelectedDateMillis", _currentDay.toDate().getTime());

  startActivityForResult(foodsActivityIntent, 200);
 

В onCreate — методе я улавливаю намерение и делаю некоторые вещи:

   Intent intent = getIntent();
  if (intent != null) {
    //Some stuff
      _foodsPagerAdapter.performSearch();
  }
 

Интересная часть здесь — «_foodsPagerAdapter.performSearch()». При этом я хочу выполнить поиск в каждом фрагменте.

 public void performSearch() {
    if (_foodSearchFragment != null)
        _foodSearchFragment.performSearch();
    if (_foodFavoritesFragment != null)
        _foodFavoritesFragment.performSearch();
    if (_foodCustomFragment != null)
        _foodCustomFragment.performSearch();
}
 

Проблема:

Как вы можете видеть, метод поиска в каждом фрагменте вызывается только в том случае, если фрагмент не равен null. Моя проблема в том, что GetItem() — метод (который инициализирует фрагменты в адаптере) вызывается после завершения метода onCreate (и OnStart). Таким образом, метод performSearch для каждого фрагмента никогда не вызывается.

Вы можете лучше понять это с помощью этого вывода Logcat:

введите описание изображения здесь

Сначала вызывается performSearch, а затем GetItem() . Но GetItem должен быть вызван первым, чтобы мой код работал.

GetItem():

 @Override
public Fragment getItem(int i) {

    Log.i("FoodActivityTest", "call getItem in FragmentPagerAdapter");

    Fragment fragment = null;

    switch (i) {
        case 0:

            if (_foodSearchFragment == null)
                _foodSearchFragment = new FoodSearchFragment();

            fragment = _foodSearchFragment;
            break;
        case 1:

            if (_foodFavoritesFragment == null)
                _foodFavoritesFragment = new FoodFavoritesFragment();

            fragment = _foodFavoritesFragment;
            break;
        case 2:

            if (_foodCustomFragment == null)
                _foodCustomFragment = new FoodCustomFragment();

            fragment = _foodCustomFragment;
            break;
    }

    return fragment;
}
 

Что я делаю не так? Нужно ли мне подходить к проблеме по-другому?

РЕДАКТИРОВАТЬ 1:

FoodsActivity:

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

    //Init some views

    _viewPager = findViewById(R.id.viewpager_foods);
    _foodsPagerAdapter = new FoodsPagerAdapter(getSupportFragmentManager(), this);
    _viewPager.setAdapter(_foodsPagerAdapter);

    handleOpenIntent();

    //do more stuff (show ads etc.)

    Log.i("FoodActivityTest", "onCreate finished");
}

@Override
protected void onStart() {
    super.onStart();

    Log.i("FoodActivityTest", "onStart finished");
}



private void handleOpenIntent() {


    Intent intent = getIntent();
    if (intent != null) {
        int navigationPosition = intent.getExtras().getInt("NavigationPosition");
        String searchQuery = intent.getExtras().getString("SearchQuery");

        _viewPager.setCurrentItem(navigationPosition);

        _foodsPagerAdapter.performSearch(searchQuery);
    }

}
 

РЕДАКТИРОВАТЬ 2:

FoodsPagerAdapter:

 public class FoodsPagerAdapter extends FragmentPagerAdapter {
private Context _context;
private FoodSearchFragment _foodSearchFragment;
private FoodFavoritesFragment _foodFavoritesFragment;
private FoodCustomFragment _foodCustomFragment;

public FoodsPagerAdapter(FragmentManager fm, Context context) {
    super(fm);

    _context = context;
}

@Override
public Fragment getItem(int i) {

    Log.i("FoodActivityTest", "call getItem in FragmentPagerAdapter");

    Fragment fragment = null;

    switch (i) {
        case 0:

            if (_foodSearchFragment == null)
                _foodSearchFragment = new FoodSearchFragment();

            fragment = _foodSearchFragment;
            break;
        case 1:

            if (_foodFavoritesFragment == null)
                _foodFavoritesFragment = new FoodFavoritesFragment();

            fragment = _foodFavoritesFragment;
            break;
        case 2:

            if (_foodCustomFragment == null)
                _foodCustomFragment = new FoodCustomFragment();

            fragment = _foodCustomFragment;
            break;
    }

    return fragment;
}

@Override
public int getCount() {
    return 3;
}

@Override
public CharSequence getPageTitle(int position) {

    switch (position) {
        case 0:
            return _context.getString(R.string.activity_foods_search);
        case 1:
            return _context.getString(R.string.activity_foods_favorites);
        case 2:
            return _context.getString(R.string.activity_foods_customfood);
        default:
            return "Error";
    }
}

public void performSearch(String query) {

    Log.i("FoodActivityTest", "call performSearch");

    if (_foodSearchFragment != null)
        _foodSearchFragment.performSearch(query);
    if (_foodFavoritesFragment != null)
        _foodFavoritesFragment.performSearch(query);
    if (_foodCustomFragment != null)
        _foodCustomFragment.performSearch(query);
}
 

Комментарии:

1. Можете ли вы предоставить всю свою FoodActivity.class ?

2. Я добавил его в упрощенной форме. Итак, что я считаю актуальным.

3. Я думаю, что нашел решение. Но не знаю, хорошее ли это решение. Кажется грязным, но, похоже, работает: _viewPager.postDelayed(new Runnable() { @Override public void run() { _foodsPagerAdapter.performSearch(SearchQuery); } }, 500);

4. adapter для понимания проблемы требуется полный код

5. Я добавил код адаптера

Ответ №1:

Вы должны иметь возможность извлекать значения из своего намерения перед инициализацией других объектов. Судя по тому, как это выглядит в настоящее время, вы пытаетесь заполнить представление без данных, а затем назначить данные позже. Чтобы решить, вы могли бы либо лучше обработать значение null в вашем адаптере, либо переместить назначение данных. Я бы, вероятно, сделал последнее.

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_foods);

// Added this.  Moved part of handleOpenIntent() here, other half is below view init.
    String searchQuery = "";
    Intent intent = getIntent();
    if (intent != null) {
        int navigationPosition = intent.getExtras().getInt("NavigationPosition");
        searchQuery = intent.getExtras().getString("SearchQuery");
    //should probably have some error handling if the SearchQuery is missing or the value is invalid.
    }
// End of additions

    //Init some views
    _viewPager = findViewById(R.id.viewpager_foods);
    _foodsPagerAdapter = new FoodsPagerAdapter(getSupportFragmentManager(), this);
    _viewPager.setAdapter(_foodsPagerAdapter);

// added this too, moved out of handleOpenIntent()
    _viewPager.setCurrentItem(navigationPosition);
    _foodsPagerAdapter.performSearch(searchQuery);
// end of additions

//removed
    //handleOpenIntent();
    //do more stuff (show ads etc.)
    Log.i("FoodActivityTest", "onCreate finished");
}