ListFragment загружает пустой список после возвращения из BackStack

это мой второй пост по тому же вопросу, я все еще жду, когда кто-нибудь направит меня. Проблема, с которой я столкнулся, может быть очень простой, короче говоря, у меня есть этот ListFragment, который заполняет список, вызывающий веб-службу, это отлично работает. Когда пользователь выбирает любой элемент, я заменяю другой фрагмент и добавляю его в BackStack

проблема начинается здесь, она выдает ListFragment, но она всегда пуста или пуста. Но я проверил журналы всеми возможными способами и обнаружил, что данные есть, но список почему-то остается пустым. Пожалуйста, помогите мне кто-нибудь...

В MainActivity я использую DrawerItemCustomAdapter и так заменяю фрагменты

private void selectItem(int position) {

    android.support.v4.app.Fragment fragment = null;

    switch (position) {
    case 0:
    {
        fragment = new EventFragment();
    }
        break;
    case 1:
        fragment = new ScheduleFragment();
        break;
    case 2:
        fragment = new NewsFragment();
        break;
    case 3:
        fragment = new TeamFragment();
        break;
    case 4:
        fragment = new VenueFragment();
        break;
    case 5:
        fragment = new NewsFragment();
        break;

    default:
        break;
    }

    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();  

        // update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        setTitle(mNavigationDrawerItemTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);

    } else {
        // error in creating fragment
        Log.e("MainActivity", "Error in creating fragment");
    }

}

в EventFragment я использую FragmentStatePagerAdapter для создания ViewPager

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.event_fragment, container, false);

    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();

    viewpager = (ViewPager)rootView.findViewById(R.id.pager);

    viewpager.setAdapter(new MyAdapter(fragmentManager));

    return rootView;
}

и в классе MyAdapter

    class MyAdapter extends FragmentStatePagerAdapter {

        FragmentManager fragmentManager;
    public MyAdapter(FragmentManager fm) {
            super(fm);
            // TODO Auto-generated constructor stub
            fragmentManager = fm;
        }

    @Override
    public Fragment getItem(int i) {
        Fragment fragment = null;

        if(i == 0)
        {
            fragment = new LiveFragment();
        }
        if(i == 1)
        {
            fragment = new UpcomingFragment();
        }
        if(i == 2)
        {
            fragment = new CompletedFragment();
        }

        return fragment;
    }
@Override
public int getCount() {
    // TODO Auto-generated method stub
    return 3;
}

@Override
    public CharSequence getPageTitle(int position) {
        if(position == 0)
        {
            return "Live";
        }
        if(position == 1)
        {
            return "Up-Coming";
        }
        if(position == 2)
        {
            return "Completed";
        }

        return null;
    }
    }

Все три вкладки - это ListFragment, давайте выберем первую

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);

        if (isVisibleToUser) {

                LiveMatchList = new ArrayList<HashMap<String, Object>>();
                adapter = null;
                Log.d("LiveMatchList setUserVisibleHint","setUserVisibleHint");
                new LoadUpcomingMatchList().execute();          
        }
    }

мой класс LoadUpcomingMatchList расширяет AsyncTask, и после onPreExecute и doInBackground я устанавливаю адаптер следующим образом

protected void onPostExecute(String file_url) {
            try
            {
                if (pDialog != null) { 
                    pDialog.dismiss();
               }
                //pDialog.dismiss();
                /**
                 * Updating parsed JSON data into ListView
                 * */
                adapter = new SimpleAdapter(
                        getActivity(),LiveMatchList,
                        R.layout.live_list_row, new String[] { TAG_DateTimeLabel, "eventName", TAG_roundName, TAG_Venue, "team1Flag", "team2Flag" },
                        new int[] { R.id.livematchDate, R.id.livematchName, R.id.liveround, R.id.livevenue, R.id.liveteam1flag, R.id.liveteam2flag });
                // updating listview
                setListAdapter(adapter);
                Log.d("LiveMatchList onPostExecute",String.valueOf(LiveMatchList));
            }
            catch(Exception ex)
            {
                Log.d("onPostExecute", ex.toString());
            }

        }

Я реализовал onListItemClick, чтобы перейти на страницу сведений из MainActivity, как вы предложили.

@Override
    public void onListItemClick(ListView l, View v, int position, long id) { 

        @SuppressWarnings("unchecked")
        HashMap<String,String> selectedItem = (HashMap<String, String>) getListView().getItemAtPosition(position);
        Bundle dataBundle = new Bundle();
        dataBundle.putString("team1Id", selectedItem.get(TAG_homeTeamId));
        dataBundle.putString("team2Id", selectedItem.get(TAG_awayTeamId));


        ((MainActivity)getActivity()).doTransaction("LiveFragment", dataBundle);

        Fragment fragment = new LiveMatchDetailMainFragment();
        fragment.setArguments(dataBundle);
        android.support.v4.app.FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.content_frame, fragment);
        fragmentTransaction.addToBackStack("LiveFragment");
        fragmentTransaction.commit();
    }

страница подробностей снова является фрагментом с реализованным viewPager. Теперь, когда я нажимаю кнопку «Назад» на странице сведений, он загружает предыдущий фрагмент, как и ожидалось, и я проверил журнал, где я вижу, что setUserVisibleHint вызывается, и вкладка загружается, как и ожидалось, но на вкладке ничего нет, должен быть список . Пожалуйста, обратитесь к диаграмме, если это поможет, большое спасибо за вашу помощь. Я уже потратил 3/4 дня на эту проблему.

   [MainActivity]
         |
         V
   [EventFragment]
   |     |      | 
   V     V      V
[Tab1] [Tab2] [Tab3]

[Tab1] — это ListFragment, реализующий onListItemClick -> Detail Fragment.




Ответы (1)


Вы выполняете свои транзакции фрагментов в своем ListFragment? Сделайте это в FragmentActivity и используйте метод обратного вызова onListItemClick() для вызова метода FragmentActivity, который должен выполнить транзакцию.

В EventFragment заменить:

FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
viewpager.setAdapter(new MyAdapter(fragmentManager));

с:

viewpager.setAdapter(new MyAdapter(getChildFragmentManager()));
person ILovemyPoncho    schedule 23.05.2014
comment
спасибо, да, я выполняю свою транзакцию в ListFragment, потому что мне нужно добавить некоторые значения в пакет и передать их в подробный фрагмент, теперь я должен создать пакет в моем ListFragment и getFragmentManager(), а затем передать их методу FragmentActivity и делать там транзакцию? и еще, метод onBackPressed() в порядке? что я написал? Еще раз спасибо. - person sk md; 23.05.2014
comment
Обычно вам нужно только передать позиции или идентификаторы из вашего onListItemClick(), указывая, какие детали элемента списка отображать. Например, в вашей FragmentActivity создайте метод showDetails(). Который получит позицию или идентификатор, переданный из onListItemClick(), он должен позаботиться о транзакции фрагмента и создать пакет для отправки в ваш DetailsFragment. При этом нет необходимости переопределять метод FragmentActivity.onBackPressed(), когда вы нажимаете кнопку «Назад» на своем смартфоне, поведение по умолчанию — вернуться к последнему фрагменту, который вы поместили в свой задний стек. - person ILovemyPoncho; 23.05.2014
comment
Хорошо, реализация метода в MainActivity и удаление onBackPressed() сработали нормально, спасибо. когда я нажимаю назад, я возвращаюсь к предыдущему фрагменту, но потом то же самое... мой ListFragment пуст, он показывает пустой экран. Я пропустил какую-то важную часть здесь? Позвольте мне дать вам сценарий: MainActivity -> Fragment (A) [FragmentStatePagerAdapter, имеет три вкладки, каждая из которых является фрагментом] Fragment (A) TB1 [является ListFragment] Fragment (A) TAB2 [является ListFragment] Fragment (A)TAB3[является ListFragment] Fragment(A)TAB1 -> DetailsFragment любое предложение? - person sk md; 23.05.2014
comment
попробуйте использовать FragmentPagerAdapter вместо FragmentStatePagerAdapter, последний уничтожает фрагмент, первый разрушает только иерархию представления, но сохраняет экземпляр. - person ILovemyPoncho; 23.05.2014
comment
Кроме того, когда вы переходите к DetailsFragment, ваши другие фрагменты должны вызывать onDestroyView(), а когда вы возвращаетесь, onCreateView() вызывается в других фрагментах, поэтому убедитесь, что вы заполняете свои представления списка в этом методе обратного вызова. Предположим, у вас есть данные в ArrayList: if(myArrayList != null) {//заполнить представление списка} - person ILovemyPoncho; 23.05.2014
comment
Большое спасибо за ваше время и усилия, так что мне нужно реализовать onDestroyView() с чем-то? есть ли способ избавиться от фрагмента в этом методе? или уничтожить? - person sk md; 23.05.2014
comment
да, не волнуйся мужик. Важной частью является заполнение списка в onCreateView(), если данные есть, когда onCreateView() вызывается, когда вы возвращаетесь из DetailsFragment, затем снова установите адаптер списка. - person ILovemyPoncho; 23.05.2014
comment
Извините, но не повезло... пробовал много способов. поэтому, когда я нажимаю назад, я вижу, что вызывается только метод setUserVisibleHint, я проверил свой список, он заполнен данными, я снова установил адаптер в методе setUserVisibleHint, но список остается пустым... и даже onDestroyView не вызывается в ListFragment. no onCreateView onCreate не вызывается в моем ListFragment, когда я нажимаю кнопку «Назад». - person sk md; 23.05.2014
comment
ну, это странно. Даже если вы используете setUserVisibleHint, ваша AsyncTask должна быть выполнена, а ваше представление списка заполнено, когда вы вернетесь из DetailsFragment. Отредактируйте свой вопрос и опубликуйте свой полный код, чтобы увидеть, что не так. - person ILovemyPoncho; 23.05.2014
comment
привет, я обновил свой вопрос, пожалуйста, посмотрите. и для получения дополнительной информации после нажатия кнопки «Назад» вызывается setUserVisibleHint, и AsyncTask работает нормально, он заполняет ArrayList и переходит к onPostExecute для setListAdapter, но все же вкладка остается пустой - person sk md; 23.05.2014
comment
наконец, использование getChildFragmentManager() вместо getSupportFragmentManager() сделало исправление, большое спасибо, я очень расстроился, потому что перепробовал так много вещей... в любом случае это ясно показывает отсутствие у меня глубоких знаний о фрагментах и ​​менеджерах. Если бы вы могли написать еще две строки, чтобы объяснить мне о getChildFragmentManager(), это было бы здорово... - person sk md; 24.05.2014
comment
Когда у вас есть вложенные фрагменты, именно так вы заставляете диспетчер фрагментов обрабатывать дочерние фрагменты. Вот и все. - person ILovemyPoncho; 24.05.2014
comment
Спасибо, это решило мою проблему final PagerAdapter adapter = new PagerAdapter (getChildFragmentManager(), tabLayout.getTabCount()); viewPager.setAdapter(adapter); iam с помощью tablayout внутри нижнего навигационного меню фрагмента. - person Muklas; 09.02.2017