Search code examples
androidandroid-fragmentsfragmentmanager

all Fragment recreating when a switching through fragments using tablayout


I am creating an application which is based on Tabs using tablayout. I didn't use viewpager. My logic is that users can create fragments (Tabs) like adding tabs in chrome so that whenever user clicks add button a new tab is created with a fragment. Now i need to save unique time stamp of each fragment created time in shared preference so that whenever i move to one fragment i can use that shared reference timestamp value to do unique function intended for that particular fragment.

But i don't know where to save that timestamp. I tried to get the time in milliseconds in Oncreate function of Fragment but whenever I switch between tabs everytime the onCreate call so that each time i switch between tabs the shared preference value changes as i added it in onCreate in Fragments.

My Logic is that it should only create once a fragment is created when user clicks add and must be able to use that in fragments.

As every time i switch to other fragement it just reinitilize all view and onCreate in called. so i could not set timestamp in oncreate..

Please help me

my Activity code is:

public class TabActivity extends AppCompatActivity{
    public static TabActivity instance;
    private FragmentChild fragmentOne;

    private TabLayout allTabs;
    ImageView add;
    ImageView imageButtonAdd2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_activity);

        getAllWidgets();
        bindWidgetsWithAnEvent();
        setupTabLayout();

    }
    public static TabActivity getInstance() {
        return instance;
    }
    private void getAllWidgets() {
        allTabs = (TabLayout) findViewById(R.id.simpleTabLayout);
        add = findViewById(R.id.addButton);
        imageButtonAdd2 = findViewById(R.id.imageButtonAdd2);
    }
    private void setupTabLayout() {
        allTabs.addTab(allTabs.newTab().setText("ONE"),true);
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                allTabs.addTab(allTabs.newTab().setText("NEW_TAB"),true);
                bindWidgetsWithAnEvent();
            }
        });
        imageButtonAdd2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*Bundle bundle = new Bundle();
                bundle.putString("data", String.valueOf(0));
                fragmentSecond = new SecondFragment();
                fragmentSecond.setArguments(bundle);
                replaceFragment(fragmentSecond,"SecondFragment");*/
            }
        });
    }
    private void bindWidgetsWithAnEvent()
    {
        allTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                setCurrentTabFragment(tab.getPosition());
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }
    private void setCurrentTabFragment(int tabPosition)
    {
        Bundle bundle = new Bundle();
        bundle.putString("data", String.valueOf(tabPosition));
        fragmentOne = new FragmentChild();
        fragmentOne.setArguments(bundle);
        replaceFragment(fragmentOne,"FirstFragment");
    }
    public void replaceFragment(Fragment fragment, String fragmentName) {
        long time= System.currentTimeMillis();
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.simpleFrameLayout, fragment,fragmentName);
        //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    public void backStackFragment(Fragment fragment, String fragmentName) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.simpleFrameLayout, fragment,fragmentName);
        ft.addToBackStack(null);
        //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    @Override
    public void onBackPressed(){
        FragmentManager fm = getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            Log.i("MainActivity", "popping backstack");
            fm.popBackStack();
        } else {
            Log.i("MainActivity", "nothing on backstack, calling super");
            super.onBackPressed();
        }
    }
} 

FragmentChild class:

public class FragmentChild extends Fragment {
    String childname;
    TextView textViewChildName;
    EditText editText;
    private GridView mGridView;
    private ListItem mListItem;
    private ListView mListview;
    private ProgressBar mProgressBar;
    private ProductViewAdapter mGridAdapter;
    private ListViewAdapter mListAdapter = null;
    private ArrayList<GridItem> mGridData;
    private ArrayList<ListItem> mListData = null;
    ListView listView;
    CheckInterNetConnection check ;
    Boolean isInternetPresent = false;
    PreferenceHelper prefs;
    private TabLayout tabLayout;
    private ViewPagerAdapter adapter;
    public static ViewPager viewPager;
    String posid = "";
    int page =0;
    String title  = "";
    TabLayout allTabs;
    int tab_position = 0;
    long time=0;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //GlobalBus.getBus().register(this);
        View view = inflater.inflate(R.layout.fragment_child, container, false);
        Bundle bundle = getArguments();
        childname = bundle.getString("data");
        Log.e("onCreateView","onCreateView");
        getIDs(view);
        setEvents();
        return view;
    }


    // Store instance variables based on arguments passed
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
         time= System.currentTimeMillis();
        page = getArguments().getInt("someInt", 0);
        title = getArguments().getString("someTitle");
        Log.e("onCreate","onCreate");
    }
    private void getIDs(View view) {
        //textViewChildName = (TextView) view.findViewById(R.id.textViewChild);
        //textViewChildName.setText(childname);
        //editText = (EditText) view.findViewById(R.id.editText);
        //editText.setText("");
    }

    private void setEvents() {

    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.e("onViewCreated","onViewCreated");

    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // Unregister the registered event.
        EventBus.getDefault().unregister(this);
    }
    public static FragmentChild newInstance(int page, String title) {
        FragmentChild fragmentFirst = new FragmentChild();
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        args.putString("someTitle", title);
        fragmentFirst.setArguments(args);
        return fragmentFirst;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e("onActivityCreated","onActivityCreated");
        allTabs = (TabLayout) getActivity().findViewById(R.id.simpleTabLayout);
        mGridView = (GridView) getView().findViewById(R.id.gridView);
        prefs = new PreferenceHelper(getActivity());
        mGridData = new ArrayList<>();
        mGridAdapter = new ProductViewAdapter(getActivity(), R.layout.grid_product_layout, mGridData);
        mGridView.setAdapter(mGridAdapter);

        mListview = (ListView) getView().findViewById(R.id.list);
        mListData = new ArrayList<>();
        mListAdapter = new ListViewAdapter(getActivity(), R.layout.list_row, mListData);
        mListview.setAdapter(mListAdapter);
        adapter = new ViewPagerAdapter(getFragmentManager(), getActivity(), viewPager, tabLayout);
    }
    @Override
    public void onStart() {
        super.onStart();
        Log.e("onStart","onStart");
        EventBus.getDefault().register(this);
        tab_position=allTabs.getSelectedTabPosition();
        //Log.e("TAB ID",String.valueOf(tab_position));
        prefs.save(String.valueOf(tab_position),"tab-"+time);
        check = new CheckInterNetConnection(getActivity());
        isInternetPresent = check.isConnectingToInternet();
        if (isInternetPresent) {
            fetchProducts(tab_position);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e("onResume","onResume");
    }

    @Override
    public void onPause() {
        EventBus.getDefault().unregister(this);
        Log.e("onPause","onPause");
        super.onPause();
    }

    @Subscribe
    public void onEvent(GlobalBus event){
        posid = event.getMessage();
        //Toast.makeText(getActivity(), event.getMessage(), Toast.LENGTH_SHORT).show();
    }

    public void fetchProducts(int tabPosition){
        String tabid = prefs.getString(String.valueOf(tabPosition),"0");
        Fragment fragment = getFragmentManager().findFragmentById(R.id.simpleFrameLayout);
        String tag = (String) fragment.getTag();
        //Log.e("URL","http://35.184.41.163/phpmyadmin/app/demo/products.php?tabid="+tabid+"&tab_position="+tabPosition);
        RestClientHelper.getInstance().get("http://35.184.41.163/phpmyadmin/app/demo/products.php", new RestClientHelper.RestClientListener() {
            @Override
            public void onSuccess(String response) {
                parseResult(response);
                mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                        try {
                            ListItem items;
                            GridItem item = (GridItem) parent.getItemAtPosition(position);
                            items = new ListItem();
                            items.setName(item.getTitle());
                            items.setType(item.getDescription());
                            mListData.add(items);
                        }
                        catch(Exception e){

                        }
                        finally {
                            mListAdapter.setGridData(mListData);
                        }
                    }
                });
            }

            @Override
            public void onError(String error) {

            }
        });
    }

    private void parseResult(String result) {
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("products");
            GridItem item;
            if(posts.length() <= 0){
                RelativeLayout ly = (RelativeLayout) getView().findViewById(R.id.noOps);
                ly.setVisibility(View.VISIBLE);
            }
            else {
               // RelativeLayout ly = (RelativeLayout)  getView().findViewById(R.id.noOps);
                //ly.setVisibility(View.INVISIBLE);
                mGridData.clear();
                mGridAdapter.setGridData(mGridData);
                for (int i = 0; i < posts.length(); i++) {
                    JSONObject post = posts.optJSONObject(i);
                    String id = post.optString("id");
                    String title = post.optString("name");
                    String description = post.optString("description");
                    String image = post.optString("image");
                    String qty = post.optString("qty");
                    String quantityin = post.optString("quantityin");
                    String price = post.optString("price");

                    item = new GridItem();
                    item.setId(id);
                    item.setTitle(title);
                    item.setDescription(description);
                    item.setImage(image);
                    item.setQuantity(qty);
                    item.setQuantityIn(quantityin);
                    item.setUnitprice(price);
                    mGridData.add(item);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        finally {
            mGridAdapter.setGridData(mGridData);
        }
    }
}

UPDATE as suggested by @Larry Hsiao

public class TabActivity extends AppCompatActivity{
    public static TabActivity instance;
    private FragmentChild fragmentOne;
    PreferenceHelper prefs;
    private TabLayout allTabs;
    ImageView add;
    ImageView imageButtonAdd2;
    private final List<Fragment> fragments = new ArrayList<>(); // maintain the instance for switching
    private int currentIndex = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_activity);
        prefs = new PreferenceHelper(TabActivity.this);
        getAllWidgets();
        //bindWidgetsWithAnEvent();
        setupTabLayout();
        bindWidgetsWithAnEvent();

    }
    public static TabActivity getInstance() {
        return instance;
    }
    private void getAllWidgets() {
        allTabs = (TabLayout) findViewById(R.id.simpleTabLayout);
        add = findViewById(R.id.addButton);
        add.performClick();
        imageButtonAdd2 = findViewById(R.id.imageButtonAdd2);
    }
    private void setupTabLayout() {
        int locfirst = allTabs.getSelectedTabPosition();
        locfirst = locfirst+1;
        allTabs.addTab(allTabs.newTab().setText("TAB"+locfirst),true);
        /*long time= System.currentTimeMillis();
        prefs.save("tab_"+locfirst,"tab_"+time);*/
        fragments.add(newFragment(0));
        addFragment(fragments.get(0));
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int loc = allTabs.getSelectedTabPosition();
                loc = loc+1;
                allTabs.addTab(allTabs.newTab().setText("TAB"+loc),true);
                fragments.add(newFragment(loc));
                addFragment(fragments.get(loc));
                /*bindWidgetsWithAnEvent();
                long time= System.currentTimeMillis();
                prefs.save("tab_"+loc,"tab_"+time);*/
            }
        });
        imageButtonAdd2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*Bundle bundle = new Bundle();
                bundle.putString("data", String.valueOf(0));
                fragmentSecond = new SecondFragment();
                fragmentSecond.setArguments(bundle);
                replaceFragment(fragmentSecond,"SecondFragment");*/
            }
        });
    }

    private Fragment newFragment(int position) {
        Fragment fragment = new FragmentChild();
        Bundle bundle = new Bundle();
        bundle.putString("position", String.valueOf(position));
        fragment.setArguments(bundle);
        return fragment;
    }


    private void addFragment(Fragment fragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.add(R.id.simpleFrameLayout, fragment);
        transaction.commit();
    }

    private void changingTab(Fragment fragment) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.hide(fragments.get(currentIndex));
        if (manager.getFragments().contains(fragment)) {
            transaction.show(fragment);
        }else {
            transaction.add(R.id.simpleFrameLayout,fragment);
        }
        transaction.commit();
    }

    private void bindWidgetsWithAnEvent()
    {
        allTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                int nextPageIndex = (currentIndex + 1) % 2; // only two fragment switching
                changingTab(fragments.get(nextPageIndex));
                currentIndex = nextPageIndex;
                //setCurrentTabFragment(tab.getPosition());
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }
    \
    @Override
    public void onBackPressed(){
        FragmentManager fm = getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            Log.i("MainActivity", "popping backstack");
            fm.popBackStack();
        } else {
            Log.i("MainActivity", "nothing on backstack, calling super");
            super.onBackPressed();
        }
    }
}

This force closes with this error:

FATAL EXCEPTION: main
                                                                 Process: com.eazypos.app, PID: 13624
                                                                 java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
                                                                     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
                                                                     at java.util.ArrayList.get(ArrayList.java:308)
                                                                     at com.eazypos.app.TabActivity$3.onTabSelected(TabActivity.java:115)
                                                                     at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1165)
                                                                     at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1158)
                                                                     at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1128)
                                                                     at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1427)
                                                                     at android.support.design.widget.TabLayout.addTab(TabLayout.java:483)
                                                                     at android.support.design.widget.TabLayout.addTab(TabLayout.java:465)
                                                                     at com.eazypos.app.TabActivity$1.onClick(TabActivity.java:62)
                                                                     at android.view.View.performClick(View.java:4780)
                                                                     at android.view.View$PerformClick.run(View.java:19866)
                                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:135)

REMOVE TAB FUNCTION

public void removeTab(int position) {
        Toast.makeText(getActivity(), "REMOVING --> "+position, Toast.LENGTH_SHORT).show();
        prefs.remove("tab_"+position);
        if (allTabs.getChildCount() > 0) {
            allTabs.removeTabAt(position);

        }
    }

Solution

  • You should maintain the Fragment instance which you already create. (With FragmentManager or just keep it with variable might do the job)

    The method setCurrentTabFragment() in Activity which creating new Fragment is invoked every time user click tab. As the result, fragment always run through the onCreate()

    // this method invoke every time user click the tab
    private void setCurrentTabFragment(int tabPosition){
        Bundle bundle = new Bundle();
        bundle.putString("data", String.valueOf(tabPosition));
        fragmentOne = new FragmentChild(); // creating new Fragment
        fragmentOne.setArguments(bundle);
        replaceFragment(fragmentOne,"FirstFragment");
    }
    

    Edited:

    • Use List to maintain the Fragment instance we already create.
    • Switch Fragment with hide()/show() provided by FragmentManager, using add() if the Fragment not added to FragmentManager before.

    Sample Code:

    public class MainActivity extends AppCompatActivity {
        private final List<Fragment> fragments = new ArrayList<>();
        private int currentIndex = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TabLayout tabLayout = findViewById(R.id.tabLayout);
    
            // initial with one page
            Fragment firstFragment = newFragment(0);
            fragments.add(firstFragment);
            addFragment(firstFragment);
            tabLayout.addTab(tabLayout.newTab().setText("Initial tab"));
    
            // user events
            findViewById(R.id.main_createTab).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    fragments.add(newFragment(tabLayout.getTabCount()));
                    tabLayout.addTab(tabLayout.newTab().setText("Pages " + tabLayout.getTabCount()));
                }
            });
    
            tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
                    int nextPageIndex = tab.getPosition();
                    if (currentIndex == nextPageIndex){
                        return;
                    }
                    changingTab(fragments.get(nextPageIndex));
                    currentIndex = nextPageIndex;
                }
                @Override public void onTabUnselected(TabLayout.Tab tab) {}
                @Override public void onTabReselected(TabLayout.Tab tab) {}
            });
        }
    
        private Fragment newFragment(int position) {
            Fragment fragment = new FragmentWithLog();
            Bundle bundle = new Bundle();
            bundle.putString("position", String.valueOf(position));
            fragment.setArguments(bundle);
            return fragment;
        }
    
        private void addFragment(Fragment fragment) {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.add(R.id.main_fragmentFrame, fragment);
            transaction.commit();
        }
    
        private void changingTab(Fragment fragment) {
            FragmentManager manager = getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.hide(fragments.get(currentIndex));
            if (manager.getFragments().contains(fragment)) {
                transaction.show(fragment);
            } else {
                transaction.add(R.id.main_fragmentFrame, fragment);
            }
            transaction.commit();
        }
    }