Git Product home page Git Product logo

testtabpager's Introduction

##UPDATE: Problem solved!

Please see my Problem Description first!

After digging into it, I have figured it out. It did have nothing to do with TabPageIndicator, all because the FragmentPagerAdapter I used.

According to this:

Implementation of PagerAdapter that represents each page as a Fragment that is persistently kept in the fragment manager as long as the user can return to the page.

This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.

So i got this,:

When you choose nav drawer item0 and slide among these tabs, every TAB's inner fragment onCreateView() , thus, all tabs' inner fragment were saved in the fragment manager.

When you choose nav drawer item1, only item0's outer fragment was onDestroyView(), all tabs' inner fragment were saved.

So when you select nav drawer item0 again, just item0's outer fragment was onCreateView() again, all tabs' inner fragment did nothing! As inner fragment's onCreateView() wasn't triggered, we see empty!

It is pretty easy to solve this problem if you know thing above, just replace FragmentPagerAdapter with FragmentStatePagerAdapter.

This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.

After using FragmentStatePagerAdapter, when you select nav drawer item0 again, all inner fragment will be re onCreateView() again! Thus, you can see all primary things in inner fragment.

But it's not perfect !

If you print all log info as i do, you will see:

  • select nav drawer item0, TAB0's and TAB1's inner fragment were onCreateView()

  • slide to TAB1, TAB2's inner fragment was onCreateView() automatically but TAB0's inner fragment was not onDestroyView()! Not what the API said:

When pages are not visible to the user, their entire fragment may be destroyed.

  • select nav drawer item1, still only item0's outer fragment was onDestroyView(), all inner fragment did nothing (I don't know what have done).

  • select nav drawer item0 again, surprisely TAB0's and TAB1's inner fragment re onCreateView() again, so we can see the TextView's text.

For these who want all active inner fragment destroyed when Item0's outer fragment destroyed, you need to keep track of all the active fragment pages and destroy them all when outer fragment is destroyed. For more information, you can see this

My new TabPageIndicatorAdapter:

class TabPageIndicatorAdapter extends FragmentStatePagerAdapter {//Change from FragmentPagerAdapter to FragmentStatePagerAdapter

        Map<Integer,Fragment> integerFragmentMap = new HashMap<Integer,Fragment>();// keep track of all the "active" fragment pages.

        public TabPageIndicatorAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            Fragment fragment=null;
            Bundle args = new Bundle();
            if(position==0)
            {
                fragment = new TabFragment0();
                args.putString("text", "This is TAB0");
                fragment.setArguments(args);
            }
            else if(position==1)
            {
                fragment = new TabFragment1();
                args.putString("text", "This is TAB1");
                fragment.setArguments(args);
            }
            else if(position==2)
            {
                fragment = new TabFragment2();
                args.putString("text", "This is TAB2");
                fragment.setArguments(args);
            }

            integerFragmentMap.put(Integer.valueOf(position),fragment);//when getItem, put it into the Map

            return fragment;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            super.destroyItem(container, position, object);

            integerFragmentMap.remove(Integer.valueOf(position));//when destroyItem, remove it from Map
        }

        public void removeAll()
        {
            Iterator iterator = integerFragmentMap.entrySet().iterator();
            while (iterator.hasNext())
            {
                Map.Entry entry = (Map.Entry)iterator.next();
                Fragment fragment = (Fragment) entry.getValue();
                fragment.onDestroyView();//Trigger inner fragment's DestroyView() method !
            }
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return TITLE[position % TITLE.length];
        }

        @Override
        public int getCount() {
            return TITLE.length;
        }
    }
@Override
    public void onDestroyView() {
        super.onDestroyView();

        tabPageIndicatorAdapter.removeAll();//when change nav drawer item to others, auto remove all inner fragment.

        Log.d("MyTag", "NEWS--onDestroyView");
    }

If you want to save which tab you chose last time, just override onViewStateRestored(Bundle savedInstanceState).

Feel free to see my code in project https://github.com/Beeder/TestTabPager

If you can read Chinese, this blog may help you understand better.



##Problem Description

I am new to android programming, recently I use navigation drawer and viewpageindicator, but i got stuck here.

Select item0, show item0 fragment with three tabs correctly, select item1, when done, select item0 again, item0 fragment with three tabs showed but only three tabs showed, the corresponding inner fragment was gone! More strangely, when I slide among these three tabs, TAB0's and TAB2's inner fragments showed again, but TAB1's inner fragment never showed! WHY?

Here is the details: According to this tutorial, I create a navigation drawer activity like this:

In order to demonstrate, only two drawer items were added. when select item 0, here goes item0 fragment(which named NewsFragment in my project):

In NewsFragment, I use JakeWharton's Android-ViewPagerIndicator, more specifically TabPageIndicator. There are three tabs, select one tab, corresponding TabFragment(x) showed.

When select drawer item1, show:

But, when I select drawer item0 again, everything was gone except the three tabs! That means the TabFragment(x)'s TextView isn't showed. WHY?

More Strangely, After I slide among these three tabs, TAB0's and TAB2's inner fragments(TextView) showed again, but TAB1's inner fragment never showed! WHY? Is that because TAB1 is in the middle?

I have tried many ways to work it out, In NewsFragment, i override onStop() and onViewStateRestored() to get the last selected tab, but tabPageIndicator.setCurrentItem(selectedItem);doesn't seem to really trigger Fragment getItem(int position) method, the selected tab's inner fragment isn't created again!

@Override
    public void onStop() {
        super.onStop();

        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putInt("NewsSelected",pager.getCurrentItem());
        editor.commit();

        Log.d("MyTag", "NEWS--onStop");
    }
@Override
    public void onViewStateRestored(Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);

        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        int selectedItem=sharedPreferences.getInt("NewsSelected",0);//Default value =0
        Toast.makeText(getActivity(), "Last time, you chose TAB"+selectedItem, Toast.LENGTH_SHORT).show();
        tabPageIndicator.setCurrentItem(selectedItem);//reselect the tab last selected. but the inner fragment isn't recreated, i got empty, why?
        //pager.setAdapter(tabPageIndicatorAdapter);
        //tabPageIndicator.setViewPager(pager);

        Log.d("MyTag", "NEWS--onViewStateRestored");
    }

I guess it has something to do with not saving InstanceState, but i don't know what else to do, I have struggled two days, I'd appreciate it if you could help me.

Thanks again.

testtabpager's People

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.