Retrieve fragment data

0

I have an Activity with 4 tabs, in each tab I load a different Fragment, in each fragment I have a fomulario, and in the last I have the Register button, when I click on Register I want to get the data of all the other fragments, I thought create a class with the data of the form and every time I pass from fragment I'm storing in an object and going from fragment to fragment, but I do not know where I'm going to feed this object, I already tried the onPause method but it does not work because fragment is not paused while accessing the other.

I put an onPause in each Fragment to test.

public void onPause(){
super.onPause();
Log.i("PAUSE", "pause A");
}

The Fragment A, B, C, and D logs are the same only by changing pause A / B / C / D. But what happens is the following, when I navigate between the tabs, it appears the information of the onPause not of that which was paused, but of the previous one. For example, I am in A, step B to B nothing happens, when I step to C, it appears in Log, "test A", when I step pro D appears "test B". And to go back is also the same thing, when I go from D to C nothing happens. Ai from C pro D appears "pause D"

Activity

package br.com.android.controledevisitas.view;

import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;
import br.com.android.controledevisitas.R;
import br.com.android.controledevisitas.adapter.ViewPagerAdapter;
import br.com.android.controledevisitas.fragment.RealizaVisitaFragmentA;
import br.com.android.controledevisitas.fragment.RealizaVisitaFragmentB;
import br.com.android.controledevisitas.fragment.RealizaVisitaFragmentC;
import br.com.android.controledevisitas.fragment.RealizaVisitaFragmentD;
import br.com.android.controledevisitas.model.Visita;

public class RealizarVisitaActivity extends FragmentActivity implements
        TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
    public Visita visita = new Visita();

    private TabHost mTabHost;
    private ViewPager mViewPager;
    private HashMap<String, TabInfo> mapTabInfo = new HashMap<String, RealizarVisitaActivity.TabInfo>();
    private PagerAdapter mPagerAdapter;

    public String teste;

    // Informação da Tab
    private class TabInfo {
        private String tag;
        private Class<?> clss;
        private Bundle args;
        private Fragment fragment;

        TabInfo(String tag, Class<?> clazz, Bundle args) {
            this.tag = tag;
            this.clss = clazz;
            this.args = args;
        }
    }

    // Um simples factory que retorna View para o TabHost
    class TabFactory implements TabContentFactory {

        private final Context mContext;

        public TabFactory(Context context) {
            mContext = context;
        }

        public View createTabContent(String tag) {
            View v = new View(mContext);
            v.setMinimumWidth(0);
            v.setMinimumHeight(0);
            return v;
        }
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Infla o layout
        setContentView(R.layout.realizavisita);
        // setContentView(R.layout.realizarvisita_a);
        // Inicializa o TabHost
        this.initialiseTabHost(savedInstanceState);
        if (savedInstanceState != null) {
            // Define a Tab de acordo com o estado salvo
            mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
        }
        // Inicializa o ViewPager
        this.intialiseViewPager();
    }

    protected void onSaveInstanceState(Bundle outState) {
        // salva a Tab selecionada
        outState.putString("tab", mTabHost.getCurrentTabTag());
        super.onSaveInstanceState(outState);
    }

    private void intialiseViewPager() {

        List<Fragment> fragments = new Vector<Fragment>();
        fragments.add(Fragment.instantiate(this,
                RealizaVisitaFragmentA.class.getName()));
        fragments.add(Fragment.instantiate(this,
                RealizaVisitaFragmentB.class.getName()));
        fragments.add(Fragment.instantiate(this,
                RealizaVisitaFragmentC.class.getName()));
        fragments.add(Fragment.instantiate(this,
                RealizaVisitaFragmentD.class.getName()));
        this.mPagerAdapter = new ViewPagerAdapter(super.getSupportFragmentManager(), fragments);
        this.mViewPager = (ViewPager) super.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(this.mPagerAdapter);
        this.mViewPager.setOnPageChangeListener(this);
    }

    private void initialiseTabHost(Bundle args) {
        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
        mTabHost.setup();
        TabInfo tabInfo = null;
        RealizarVisitaActivity.AddTab(this, this.mTabHost, this.mTabHost
                .newTabSpec("Tab1").setIndicator("A"), (tabInfo = new TabInfo(
                "Tab1", RealizaVisitaFragmentA.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        RealizarVisitaActivity.AddTab(this, this.mTabHost, this.mTabHost
                .newTabSpec("Tab2").setIndicator("B"), (tabInfo = new TabInfo(
                "Tab2", RealizaVisitaFragmentB.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        RealizarVisitaActivity.AddTab(this, this.mTabHost, this.mTabHost
                .newTabSpec("Tab3").setIndicator("C"), (tabInfo = new TabInfo(
                "Tab3", RealizaVisitaFragmentC.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        RealizarVisitaActivity.AddTab(this, this.mTabHost, this.mTabHost
                .newTabSpec("Tab4").setIndicator("D"), (tabInfo = new TabInfo(
                "Tab4", RealizaVisitaFragmentD.class, args)));
        this.mapTabInfo.put(tabInfo.tag, tabInfo);
        mTabHost.setOnTabChangedListener(this);
    }

    private static void AddTab(RealizarVisitaActivity activity,
            TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
        // Attach uma Tab view factory para o spec
        tabSpec.setContent(activity.new TabFactory(activity));
        tabHost.addTab(tabSpec);
    }

    public void onTabChanged(String tag) {
        // Avisa para o mViewPager qual a Tab que está ativa
        int pos = this.mTabHost.getCurrentTab();
        this.mViewPager.setCurrentItem(pos);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset,
            int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        this.mTabHost.setCurrentTab(position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    public void onResume() {
        super.onResume();

    }

    public void onPause() {
        super.onPause();
    }
}

ViewPagerAdapter

package br.com.android.controledevisitas.adapter;

import java.util.List;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class ViewPagerAdapter extends FragmentPagerAdapter{
     private List<Fragment> mFragments;

      public ViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);

        mFragments = fragments;
      }

      @Override
      public Fragment getItem(int i) {  
        return mFragments.get(i);
      }

      @Override 
      public int getCount() {
        return mFragments.size();
      }
}
    
asked by anonymous 28.07.2014 / 19:43

1 answer

0

To better understand why onPause of Fragment A is only called when going to Fragment C , I'll try to explain the behavior of ViewPager .

ViewPager, by default, only stores 2 items in memory. What is visible and the next one, for the transition effect to be more fluid.

The OffscreenPageLimit attribute controls this effect , by default it is 1.

If in your case the Layouts is simple, you can set it to 3, so that none of your Fragments is destroyed.

For the data loss problem, there are two ways to approach the problem:

  • Set OffscreenPageLimit from ViewPager to 3, so no Fragment will be destroyed. And the data will not be lost. Just accessing Fragments through Adapter to retrieve data. I stress that this is only a good alternative if Layouts are not complex, so there is not too much memory spending
  • When Fragment is destroyed, that is, when the onDestroyView method is called. Just save the data in Activity . In your Fragment would have something like:

    @Override
    public void onDestroyView() {
        // Usar o método findViewById, pegando os dados que for de interesse
        // Nesse caso há duas formas:
        //  1. Acessar a instância da Activity com getActivity(), fazer um cast e ir setando os dados.
        ((SuaActivity) getActivity()).salvarDados(...);
        //  2. Criar um Listener, setar e chama-lo nesse momento passando os dados
        mSaveStateListener.salvarDados(...);
    
        super.onDestroyView(); // Chamar o metodo da superclasse
    }
    

    The second form involves: Creating an interface Listener , set Listener in each Fragment through Activity . This Listener will be called to save the data when Fragment is destroyed.

  • To access the Fragments that are in Adapter , and retrieve the form data, you can do this within the activity:

    public void confirmaFormulario() {
        RealizaVisitaFragmentA visitaA = mAdapter.getItem(0);
        RealizaVisitaFragmentB visitaB = mAdapter.getItem(1);
        // Mesma coisa com os demais fragmentos
    
        // Chama os metodos do Fragment para recuperar os dados
    }
    

    This method should be called when the button that is in Fragment 4 is clicked.

        
    28.07.2014 / 22:17