3

this is my 2nd post on same matter, I am still waiting for someone to guide me. The issue I am facing may be very simple, in short I have this ListFragment which populates the list calling a webservice, this works fine. When user selects any item I replace another fragment and add this one to BackStack

the issue starts here, it pops the ListFragment but it's always empty or blank. But I've checked logs in every possible way and found the data is there, for some reason the list stays blank. Please help me someone...

In MainActivity I use DrawerItemCustomAdapter and this is how I replace fragments

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

}

in EventFragment I use FragmentStatePagerAdapter to create 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;
}

and In the MyAdapter class

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

All three tabs are ListFragment let's pick the first one

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

my LoadUpcomingMatchList class extends AsyncTask, and after onPreExecute and doInBackground I set the adapter like this

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

        }

I've implemented onListItemClick to goto details page from MainActivity, like you suggested.

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

the detail page is again a fragment with viewPager implemented. Now when I press back button from detail page it loads the previous fragment as expected and I've checked the log where I can see setUserVisibleHint is called and the tab is loaded as expected but there is nothing in the tab, there should be a list. please refer to the diagram, if that helps, thank you so much for your help. I've wasted 3/4 days on this issue already.

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

[Tab1] is a ListFragment implements onListItemClick -> Detail Fragment.

Blo
  • 11,903
  • 5
  • 45
  • 99
sk md
  • 83
  • 1
  • 10

1 Answers1

6

Are you doing your fragment transactions within your ListFragment? Do that in the FragmentActivity and use your onListItemClick() callback method to call a FragmentActivity method, which should run the transaction.

In EventFragment replace:

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

with:

viewpager.setAdapter(new MyAdapter(getChildFragmentManager()));
ILovemyPoncho
  • 2,762
  • 2
  • 24
  • 37
  • thank you, yes I am doing my transaction in the ListFragment because I have to add some values to bundle and pass that on to the detailed fragment, now should I create the bundle in my ListFragment and the getFragmentManager() then pass them to the method of FragmentActivity and do the transaction there? and another thing is the onBackPressed() method fine? that I've wrote? Thank you again. – sk md May 23 '14 at 02:52
  • Usually, you only need to pass positions or id's from your onListItemClick(), indicating which list item "details" to show. On your FragmentActivity create a method showDetails() for example. Which will receive the position or id passed from onListItemClick(), it should take care of the fragment transaction and creating the bundle to send to your "DetailsFragment". Doing that there is no need to override the FragmentActivity.onBackPressed() method, when you press the back button on your smartphone, the default behavior is to go back to the last fragment you put on your back stack. – ILovemyPoncho May 23 '14 at 03:27
  • Good one, implementing the method in MainActivity and removing the onBackPressed() worked fine, thank you. when I press back it brings me to previous fragment but then same thing... my ListFragment is empty, it shows a blank screen. Am I missing some inportant part here? Let me give yo the scenario: MainActivity -> Fragment(A)[FragmentStatePagerAdapter, has three swiping tabs, each of them is a Fragment] Fragment(A)TB1[ is a ListFragment] Fragment(A)TAB2[ is a ListFragment] Fragment(A)TAB3[ is a ListFragment] Fragment(A)TAB1 -> DetailsFragment any suggestion? – sk md May 23 '14 at 04:06
  • try using FragmentPagerAdapter instead of FragmentStatePagerAdapter, the last one destroy the fragment, the first one only destroys the view hierarchy, but it keeps the instance. – ILovemyPoncho May 23 '14 at 04:12
  • also, when you are going to the DetailsFragment, your other fragments should be calling onDestroyView() and when you go back, onCreateView() is called in you other fragments, so make sure you are filling your list views in that callback method. Supposing you have your data in an ArrayList: if(myArrayList != null) { //fill list view } – ILovemyPoncho May 23 '14 at 04:40
  • Thanks a lot for your time and effort man, so do I need to implement onDestroyView() with something? is there a way to dispose the fragment in that method? or destroy? – sk md May 23 '14 at 05:10
  • yeah, don't worry man. The important part is to fill the list in onCreateView(), if the data is there when onCreateView() is called when you go back from DetailsFragment, then set the list adapter again. – ILovemyPoncho May 23 '14 at 05:35
  • Sorry to say, no luck... tried a lot of ways. so when I press back I see only setUserVisibleHint method is being called, I've checked my List, it's filled with data, I've set the adapter again in the setUserVisibleHint method still the list comes empty... and even onDestroyView is not called in the ListFragment. no onCreateView no onCreate is called in my ListFragment when I press back button. – sk md May 23 '14 at 07:07
  • well, that's weird. Even if you are using setUserVisibleHint your AsyncTask should be executed and your list view filled when you go back from DetailsFragment. Edit your question and post your full code, to see what's wrong. – ILovemyPoncho May 23 '14 at 15:14
  • hello there, I've updated my question, please have a look. and for more information after pressing back button setUserVisibleHint gets called and AsyncTask works fine, it fills the ArrayList and goes till onPostExecute to setListAdapter but still Tab comes empty – sk md May 23 '14 at 16:22
  • finally using getChildFragmentManager() instead-of getSupportFragmentManager() did the fix, thank you so much, I got very frustrated because I tried so many things... any way this clearly shows my lack of depth knowledge on fragments and managers. If you could write two lines more to explain about the getChildFragmentManager() to me, that would be awesome... – sk md May 24 '14 at 02:35
  • When you have nested fragments, that's how you get the fragment manager to handle the child fragments. That's it. – ILovemyPoncho May 24 '14 at 03:58
  • Thanks, this resolved my issue `final PagerAdapter adapter = new PagerAdapter (getChildFragmentManager(), tabLayout.getTabCount()); viewPager.setAdapter(adapter);` iam using tablayout inside fragment bottomnavigation menu – Muklas Feb 09 '17 at 05:59