2016-01-15 21 views
6

Ich habe 3 Swipes Tabs (A, B, C) in meinem Android. Wenn Tabs c kommt, habe ich eine Funktion RetrieveData(), die verwendet wird, um die Daten von MySQL abzurufen und in listView zu laden.Stop Funktion Aufruf in Tabs

Angenommen, in MySQL habe ich nur eine Zeile Daten, wenn es zu c kommt, werden die Daten in listView geladen (nur eine Liste). Wenn ich zu Tab A wische und erneut zu C wische, wird die Liste jetzt zu 2. Gibt es eine Möglichkeit, den RetrieveData() nur einmal anzurufen? Vielen Dank.

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View edit_details = inflater.inflate(R.layout.edit_work_details, container, false); 
     // EditDetails = new ArrayList<HashMap<String, String>>(); 
     listViewUpdate = (ListView) edit_details.findViewById(R.id.listViewEdit); 
     totalHours=(TextView)edit_details.findViewById(R.id.hour); 
     setHasOptionsMenu(true); 
     Bundle bundle = this.getArguments(); 
     if (getArguments() != null) { 
      ID = bundle.getString("ID"); 
      RetrieveData(ID); // retrieve data from MySQL 
     } 
     Toast.makeText(getActivity(), "Details" + ID, Toast.LENGTH_LONG).show(); 
     } 

TabAdapter

public class TabsFragmentPagerAdapter extends FragmentPagerAdapter { 

    public TabsFragmentPagerAdapter(FragmentManager fm) { 
     super(fm); 
     // TODO Auto-generated constructor stub 
    } 

    @Override 
    public Fragment getItem(int index) { 
     // TODO Auto-generated method stub 

     if(index == 0) { 

      Fragment fragment=new A(); 
      Bundle bundle = new Bundle(); 
      bundle.putString("ID", Edit.ID); 
      fragment.setArguments(bundle); 
      return fragment; 

     } 
     if(index == 1) { 
      Fragment fragment = new B(); 
      Bundle bundle = new Bundle(); 
      bundle.putString("ID", Edit.ID); 
      fragment.setArguments(bundle); 
      return fragment; 
     } 

     if(index == 2) { 
      Fragment fragment = new C(); 
      Bundle bundle = new Bundle(); 
      bundle.putString("ID", Edit.ID); 
      fragment.setArguments(bundle); 
      return fragment; 
     } 

     return null; 
    } 

    @Override 
    public int getCount() { 
     // TODO Auto-generated method stub 
     return 3; 
    } 

} 

ViewPager Code

public class ActivityB extends ActionBarActivity implements ActionBar.TabListener { 

    private ViewPager viewPager; 
    private ActionBar actionBar; 
    private TabsFragmentPagerAdapter tabsAdapter; 
    private String[] item = new String[]{"Information","Work Force","Work Details"}; 
    private String id; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_b); 
//  id=getIntent().getExtras().getString("ID"); 
     viewPager = (ViewPager) findViewById(R.id.viewPager); 
     tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager()); 
     viewPager.setAdapter(tabsAdapter); 
     actionBar = getSupportActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     for(int i=0; i<4; i++){ 
      actionBar.addTab(actionBar.newTab().setText(item[i]).setTabListener(this)); 
     } 
     viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 

      @Override 
      public void onPageSelected(int arg) { 
       // TODO Auto-generated method stub 
       actionBar.setSelectedNavigationItem(arg); 
      } 

      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) { 
       // TODO Auto-generated method stub 

      } 

      @Override 
      public void onPageScrollStateChanged(int arg0) { 
       // TODO Auto-generated method stub 

      } 
     }); 

    } 



    @Override 
    public void onTabReselected(ActionBar.Tab arg0, FragmentTransaction arg1) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction arg1) { 
     // TODO Auto-generated method stub 
     viewPager.setCurrentItem(tab.getPosition()); 
    } 

    @Override 
    public void onTabUnselected(ActionBar.Tab arg0, FragmentTransaction arg1) { 
     // TODO Auto-generated method stub 

    } 

} 

Das ist mein Tab c

enter image description here

Nach Streichen auf A und C wieder

enter image description here

Scheint, wie es RetrieveData wieder aufrufen.

+0

teilen Sie Ihre Code – playmaker420

+0

@ playmaker420 berechne erneut –

+0

Code für Ihre retrieveData() -Funktion? Übrigens ist es üblich, dass der Funktionsname mit einem kleinen Fall beginnt. Nur der Klassenname sollte groß beginnen. – Jiyeh

Antwort

1

Sie sollten setOffscreenPageLimit von ViewPager verwenden. Es wird festgelegt, wie viele Pager Seiten Sie zuerst laden möchten.

Der Standardwert für setOffScreeenPageLimit ist 1, daher wird die aktuelle Seite und die nächste Seite geladen. In Ihrem Fall wird es laden A und B, wenn Sie zu C von B verschieben wird es Instanz A zerstören.

versuchen

`pager.setOffscreenPageLimit(2)` 

verwendet, wird es aktuelle Seite und 2 weitere Seiten laden, so A, B und C einmal geladen werden.

EDIT

Die Anzahl der Seiten, die auf beiden Seiten der aktuellen Seite in der Ansichtshierarchie in einem Ruhezustand gehalten werden sollen. Seiten über diese Grenze werden bei Bedarf vom Adapter neu erstellt.

Dies wird als Optimierung angeboten. Wenn Sie im Voraus die Nummer der Seiten kennen, die Sie unterstützen müssen oder Lazy-Loading-Mechanismen in auf Ihren Seiten haben, kann das Optimieren dieser Einstellung Vorteile in wahrgenommene Weichheit von Paging-Animationen und Interaktion haben.Wenn Sie eine kleine Anzahl von Seiten (3-4) haben, die Sie alle auf einmal aktiv halten können, wird weniger Zeit im Layout für neu erstellte Ansichtsbaumstrukturen als die Benutzerseiten hin und her verbracht.

Source

Es eindeutig heißt, dass Sie Anzahl der Seiten einstellen können Sie bei der ersten Stufe laden möchten, wenn Sie 5 Seiten auf den ersten Lauf geladen werden soll, setzen Sie den Wert auf 4.

Jetzt Wenn Sie von einer der Seiten zwischen 5 Seiten wechseln, wird onCreateView() von Fragment nicht aufgerufen, da es bereits in der Anfangsphase geladen ist.

1

Sie können dies verhindern, indem Sie die OffscreenPageLimit auf 2 auf Ihre ViewPager Instanz setzen. Hier ist die docs -

/** 
    * Set the number of pages that should be retained to either side of the 
    * current page in the view hierarchy in an idle state. Pages beyond this 
    * limit will be recreated from the adapter when needed. 
    * 
    * <p>This is offered as an optimization. If you know in advance the number 
    * of pages you will need to support or have lazy-loading mechanisms in place 
    * on your pages, tweaking this setting can have benefits in perceived smoothness 
    * of paging animations and interaction. If you have a small number of pages (3-4) 
    * that you can keep active all at once, less time will be spent in layout for 
    * newly created view subtrees as the user pages back and forth.</p> 
    * 
    * <p>You should keep this limit low, especially if your pages have complex layouts. 
    * This setting defaults to 1.</p> 
    * 
    * @param limit How many pages will be kept offscreen in an idle state. 
    */ 
    public void setOffscreenPageLimit(int limit) { 
     if (limit < DEFAULT_OFFSCREEN_PAGES) { 
      Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " + 
        DEFAULT_OFFSCREEN_PAGES); 
      limit = DEFAULT_OFFSCREEN_PAGES; 
     } 
     if (limit != mOffscreenPageLimit) { 
      mOffscreenPageLimit = limit; 
      populate(); 
     } 
    } 
1

Wenn Sie von der DB sind das Abrufen jedes Mal, wenn Sie auf C Swipe, dann müssen Sie die Liste vor der Hand löschen, entweder in der onResume Methode, wenn Sie das Fragment eingeben oder in der Methode, wenn Sie das Fragment hinterlassen .

Dies bedeutet entweder löschen Sie ArrayList zum Beispiel, und stellen Sie sicher, es ist nicht static, sonst bedeutet es Sie Ihre ListView unter Verwendung listView.setAdapter(null); löschen müssen. Dann vergessen Sie nicht, notififyDatasetChanged() auf dem Adapter zu verwenden.

+0

können Sie mehr erklären? Danke –

+1

In 'RetrieveData (ID)', stellen Sie eine 'Liste' von irgendeiner Art ein und übergeben diese in Ihren' ListView Adapter'. Löschen Sie einfach diese 'list' am Anfang von' RetrieveData (ID) 'und es sollte funktionieren, egal wie groß 'setOffscreenPageLimit' ist. – eoinzy

1

Da Sie Ihren RetrieveData() - Code nicht eingefügt haben, gehe ich davon aus, dass Sie die Daten in eine ArrayList <> lesen oder über den Cursor iterieren.Auch gibt es keine anderen Stellen, an denen Sie diese Methode aufrufen onCreateVie() . Einige der möglichen Lösungen sein kann:

  1. Wenn Sie explizit viewPager.setOffscreenPageLimit (x) setzen, wobei x> 1 ist, diesen Code entfernen. Standardmäßig ist dieser Wert 1 und der Pager ruft createView jedes Mal auf.
  2. Da Sie FragmentPagerAdapter verwenden, sollte das C-Fragment, nachdem Sie es idealerweise geladen haben, nicht neu erstellt werden, da es im Speicher vorhanden sein sollte und ViewPager es verwenden wird. Überprüfen Sie, ob onCreateView() jedes Mal aufgerufen wird für C-Fragment.
  3. Bitte stellen Sie sicher, dass Sie nicht jedes Mal, wenn Sie Ihre Daten in eine Liste aufnehmen, an die Liste anhängen, anstatt die Liste zu löschen und dann hinzuzufügen.

Bitte versuchen Sie es oben.

1

Viele Antworten vorschlagen setOffscreenseiteLimit, aber ich würde es aus 2 Gründen nicht empfehlen.

1) Die Ressourcen eines Fragments in viewpager werden nicht mit Garbage Collection erfasst, auch wenn der Bildschirm nicht mehr angezeigt wird. Dies führt zu Speicherproblemen, wenn Sie Objekte wie Bitmaps im Speicher haben.

2) Dieser Ansatz wird nicht ausreichen, wenn die App in den Hintergrund tritt und wieder in den Vordergrund tritt.

Ich empfehle Ihnen, Ihre Daten in jedem Fragment in Ihrem ViewPager in onSaveInstanceState zu speichern und zu prüfen, ob in onCreate Daten gespeichert sind. Wenn Daten vorhanden sind, zeigen Sie sie an. Andernfalls Abfrage für die Daten.

1

Ich habe ein ähnliches Problem irgendwann zurück, Problem war mit meinem Code, beim Abrufen von Datum aus DB, ich war die Liste füllen, und wenn Seite aktualisiert wird keine neue Liste erstellen, es wurde direkt die gleichen Daten hinzufügen in der Liste, die bereits die Daten enthält und zwei Zeilen mit demselben Eintrag zeigt. Um dieses Problem zu lösen, habe ich meine Liste gelöscht, bevor ich die Daten bevölkert habe.

+0

Wie lösche ich die Liste? –

+1

Benutzer list.clear(); oder Sie können die Liste neu initialisieren, damit alle Daten gelöscht werden – Arshad