web-dev-qa-db-fra.com

Android comment arrêter la régénération des fragments lors du changement d'onglet

J'ai le code suivant :

MainActivity.Java

package com.erc.library;

import Java.io.BufferedInputStream;
import Java.io.File;
import Java.io.FileOutputStream;
import Java.io.InputStream;
import Java.net.URL;
import Java.net.URLConnection;

import Android.app.ActionBar;
import Android.app.ActionBar.Tab;
import Android.app.FragmentTransaction;
import Android.content.SharedPreferences;
import Android.content.res.Resources;
import Android.graphics.Color;
import Android.os.Bundle;
import Android.os.Environment;
import Android.os.StrictMode;
import Android.support.v4.app.FragmentActivity;
import Android.support.v4.view.ViewPager;
import Android.view.Menu;
import Android.view.MenuInflater;
import Android.view.MenuItem;
import Android.widget.TextView;
import Android.widget.Toast;

import com.erc.sayeghlibrary.adapter.TabsPagerAdapter;

public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {

    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;
    // Tab titles
    private String[] tabs = { "Stories", "Dictionaries", "eBooks"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);






        int actionBarTitleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "Android");
        if (actionBarTitleId > 0) {
            TextView title = (TextView) findViewById(actionBarTitleId);
            if (title != null) {
                title.setTextColor(Color.WHITE);
            }
        }       

        // Initilization
        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


        // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name)
                    .setTabListener(this));
        }

        /**
         * on swiping the viewpager make respective tab selected
         * */
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });







    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // on tab selected
        // show respected fragment view
        viewPager.setCurrentItem(tab.getPosition());


    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }






       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.main, menu);
         return true;
       } 




       @Override
       public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
         // action with ID action_refresh was selected
         case R.id.Favorites:
           Toast.makeText(this, "Favorites selected", Toast.LENGTH_SHORT)
               .show();
           break;
         // action with ID action_settings was selected

         default:
           break;
         }

         return true;
       } 


}

TabsPagerAdapter.Java

package com.erc.library.adapter;

import com.erc.library.Dictionaries;
import com.erc.library.Ebooks;
import com.erc.library.Stories;

import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentPagerAdapter;

public class TabsPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:

            return new Stories();
        case 1:

            return new Dictionaries();
        case 2:
            // Movies fragment activity
            return new Ebooks();
        }

        return null;
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 3;
    }

}

Je crée une application de bibliothèque dans laquelle la navigation se fait par onglets, le problème est à chaque fois que je passe du troisième onglet au premier ou du premier au troisième, le contenu des onglets est rafraîchissant, je veux empêcher le rafraîchissement, tout Aidez-moi, s'il vous plaît ?

36
Monzer Yaghi

Par défaut, ViewPager recrée les fragments lorsque vous balayez la page. Pour éviter cela, vous pouvez essayer l'une des trois choses suivantes:

1. Dans la onCreate() de vos fragments, appelez setRetainInstance(true).

2. Si le nombre de fragments est fixe et relativement petit, alors dans votre onCreate() ajoutez le code suivant:

mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(limit);         /* limit is a fixed integer*/

3. Utilisez un FragmentPagerAdapter dans le cadre de votre ViewPager.

Si je me souviens bien, la deuxième option est plus prometteuse. Mais je vous exhorte à essayer les trois et à voir lesquels fonctionnent.

107
Y.S

il faut d'abord instance de FragmentPagerAdapter, puis .getCount() retournera une valeur -

tandis que .getCount() - 1 doit être défini comme limite hors écran par défaut:

TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager());

/* the ViewPager requires a minimum of 1 as OffscreenPageLimit */
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);

ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);
21
Martin Zeitler

vous pouvez gérer les loisirs de la vue en vérifiant si la vue est nulle ou non

public class FragmentExample extends Fragment {

    private View rootView;

    public FragmentExample() {}

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

    if (rootView == null) {

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

        // Initialise your layout here

    } else {
        ((ViewGroup) rootView.getParent()).removeView(rootView);
    }

    return rootView;
    }
}
4
Ahmad Nasser

Dans onCreate () de vos fragments, appelez setRetainInstance (true)

3
Mohsen mokhtari

Un peu tard pour cette question, mais grâce à Y.S., j'ai appris comment fonctionne ViewPager. Je construisais une application avec 4 onglets et à tout moment, j'ai remarqué que seulement deux onglets étaient en cours d'actualisation, ce qui, je suppose, était un comportement par défaut. Après des heures d'enquête, j'ai compris que Android rafraîchit plusieurs onglets pour apporter une performance de balayage fluide à l'utilisateur - vous remarquerez peut-être que vous auriez cliqué sur tab2, mais Android apporte les données de tab3 et les garde prêtes.

Bien que ce comportement soit bon, il a ses avantages et ses inconvénients. Avantages - vous obtenez une expérience de balayage fluide, sans que les données soient chargées à partir d'un serveur externe lorsque vous atterrissez dans cet onglet. Contre-votre implémentation de backstack dans les onglets pourrait aller de pair. Lorsque vous cliquez sur un onglet, le téléavertisseur de vue appelle en fait un onglet plus fluide et vous vous retrouverez dans un gros problème, si vos méthodes configurent backarrow (home) en haut à gauche en fonction de ce qui se trouve dans la backstack dans l'onglet cliqué.

setOffscreenPageLimit est la réponse à cela. Si vous souhaitez que votre infrastructure de backstack personnalisée fonctionne et que vous ne voulez pas que tab3 soit appelé lorsque vous cliquez sur tab2, vous devez simplement définir la valeur sur le nombre d'onglets. Par exemple, si vous avez 4 onglets, définissez setOffScreePageLimit (4). Cela signifierait que Android rafraîchirait initialement les 4 fragments, ce qui est un peu un surcoût de performance (que vous devriez gérer correctement). Mais, votre backstack et changement de tabulation restent intacts. aide.

Étant donné que l'activité implémente ActionBar.TabListener, onCreate () de l'activité est appelée à plusieurs reprises. Placez donc le code suivant dans la méthode onResume ():

   // Initilization
    viewPager = (ViewPager) findViewById(R.id.pager);
    actionBar = getActionBar();
    mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

    viewPager.setAdapter(mAdapter);
    actionBar.setHomeButtonEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


    // Adding Tabs
    for (String tab_name : tabs) {
        actionBar.addTab(actionBar.newTab().setText(tab_name)
                .setTabListener(this));
    }

    /**
     * on swiping the viewpager make respective tab selected
     * */
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            // on changing the page
            // make respected tab selected
            actionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
1
Nagabhushan Baddi

Dans mon cas, la suggestion ci-dessus ne fonctionne pas.

Pour restreindre la recréation d'un fragment, ce que j'ai fait:

Dans onCreateView, vous pouvez stocker la vue gonflée dans une variable globale et l'initialiser uniquement si elle est null, comme dans ce code:

    var root:View?=null
    var apiDataReceived=false
 override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    if (root==null)
        root=inflater!!.inflate(R.layout.fragment_layout, container, false)
    return root
}

Maintenant, si vous analysez des données et les remplissez dans RecyclerView ou tout autre View

  1. Créez une variable globale comme dans le code ci-dessus apiDataReceived

  2. Définissez-le sur true si vous avez correctement analysé les données.

  3. Avant apiCalls, placez une condition comme celle-ci:

    if (! apiDataReceived) {apiCalls ()}

Donc, si apiCalls () ne sera appelé que si les données ne sont pas analysées.

Faites vos appels http et votre analyse ou toute autre chose dans la méthode qui a appelé après onCreateView comme onStart

Le code ci-dessus est en kotlin, si vous rencontrez un problème, faites-le moi savoir dans les commentaires.

0
Suraj Vaishnav