18
erfrischende

Ich habe den folgenden Code:Android, wie Fragmente auf der Registerkarte ändern zu stoppen

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

} 

Ich mache eine Bibliotheksanwendung, bei der die Navigation über Tabs erfolgt, ist das Problem jedes Mal, wenn ich von der dritten Registerkarte auf die Fi gehe ersten oder ersten bis dritten, der Tab-Inhalt ist erfrischend, ich möchte die Aktualisierung zu verhindern, Irgendwelche Hilfe bitte?

+0

Ok ich die Lösung gefunden habe, habe ich die folgende Zeile setzen sollte: viewPager.setOffscreenPageLimit (die Anzahl der Tabs); –

Antwort

62

Standardmäßig erstellt ViewPager die Fragmente beim Wischen der Seite neu. Um dies zu verhindern, können Sie eines von zwei Dingen versuchen:

1. Im onCreate() Ihrer Fragmente, rufen setRetainInstance(true).

2. Wenn die Anzahl der Fragmente fixiert ist & relativ klein ist, dann in Ihrem onCreate() fügen den folgenden Code:

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

Wenn ich mich richtig erinnere, die zweite Option ist vielversprechend. Aber ich fordere Sie auf, beides zu versuchen und zu sehen, welche von ihnen arbeiten.

+1

Das Zurückhalten von Fragmenten wird in diesem Fall nicht funktionieren, und das Zurückhalten ist im Allgemeinen eine schlechte Übung, da es Speicherlecks schwer aufspüren kann, wenn es ohne Vorsicht verwendet wird. Ich werde hier eine zweite Option verwenden, weil Sie ViewPager sagen - "speichere X Fragmente für mich". Und das ist es – Gaskoin

+0

Ja, wie Sie gesagt haben, sollte die erste Option vernünftig verwendet werden ... obwohl es funktioniert;) –

+0

Große Antwort. SetOffScreenLimit() arbeitete für mich. – JakeWilson801

1

Da die Aktivität ActionBar.TabListener implementiert, wird die onCreate() -Aktivität immer wieder aufgerufen. So legen Sie den folgenden Code in onResume() -Methode:

// 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) { 
     } 
    }); 
16

man Instanz hat den FragmentPagerAdapter zuerst, dann .getCount() einen Wert zurück -

während .getCount() - 1 sollte als Standard-Off-Screen-Grenze festgelegt werden:

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); 
+2

Sie sparen mein Leben. Aber wünschen Sie mehr über 'ViewPager.setOffscreenPageLimit()' Methode zu erklären. –

+0

@ SadeqShajary es ist in der Dokumentation erklärt, wahrscheinlich besser als ich es jemals könnte: https://developer.android.com/reference/android/support/v4/view/ViewPager.html#setOffscopePageLimit (null) –

+0

pefect, danke! –

4

Sie Ansicht Erholung per Scheck umgehen kann, wenn die Ansicht

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; 
    } 
} 
null ist oder nicht
0

Ein wenig spät zu dieser Frage, aber dank Y.S., lernte, wie ViewPager funktioniert. Ich habe eine App mit 4 Tabs erstellt und zu jedem Zeitpunkt festgestellt, dass nur zwei Tabs aktualisiert wurden, was vermutlich ein Standardverhalten war. Nach stundenlanger Untersuchung habe ich verstanden, dass Android mehrere Tabs aktualisiert, um eine reibungslose Wischperformance für den Benutzer zu erzielen - Sie haben vielleicht bemerkt, dass Sie Tab2 angeklickt hätten, aber Android bringt die Daten für Tab3 ein und hält sie bereit.

Obwohl dieses Verhalten gut ist, hat es seine Vor- und Nachteile. Vorteile - Sie erhalten eine reibungslose Wischbedienung, ohne dass Daten von einem externen Server geladen werden, wenn Sie in diesem Tab landen. Cons-Ihre Backstack-Implementierung in Tabs könnte für einen Wurf gehen. Wenn Sie auf eine Registerkarte klicken, ruft der Ansichts-Pager tatsächlich eine glattere Registerkarte auf, und Sie werden in große Schwierigkeiten geraten, wenn Ihre Methoden links oben auf der Grundlage des Backstacks in der angeklickten Registerkarte Backarrow (Home) einrichten.

setOffscreenseiteLimit ist die Antwort darauf.Wenn Sie möchten, dass Ihr benutzerdefiniertes Backstack-Framework funktioniert und tab3 nicht aufgerufen werden soll, wenn auf tab2 geklickt wird, müssen Sie lediglich den Wert auf die Anzahl der Registerkarten festlegen. Wenn Sie beispielsweise 4 Registerkarten haben, setzen Sie setOffScreePageLimit (4). Dies würde bedeuten, dass Android alle 4 Fragmente zu Beginn aktualisieren würde, was ein bisschen Leistungsüberhang ist (was Sie richtig verwalten sollten). Aber Ihr Backstack- und Tab-Switching bleibt erhalten. Hoffe das hilft.

2

Im onCreate() Ihrer Fragmente, rufen setRetainInstance (true)

+0

anstelle von 'setRetainInstance (true)' könnte man einen 'FragmentStatePagerAdapter' verwenden (es hängt davon ab, was das beabsichtigte Verhalten sein soll, wie die SDK-Dokumentation liest:" der Fragmentlebenszyklus wird etwas anders sein, wenn eine Aktivität neu erstellt wird "). –

Verwandte Themen