Ich verwende 3 Fragments
innerhalb einer Viewpager
, das Problem ist, dass ich große Datenmengen in eine Asynctask
und Lader lade. Auf Geräten wie HTC one
funktioniert es einwandfrei, auf Low-End-Geräten nimmt es jedoch viel Zeit in Anspruch. Dies liegt hauptsächlich daran, dass ich beim Implementieren der pagerAdapter
die Fragmente in eine ArrayList
lege. Dadurch werden die Fragmente instanziiert, wenn die Hauptaktivität geladen wird. Was ich brauche ist, dass es nur das erste Fragment (main) "lädt" und wenn der Benutzer Swype
, das andere Fragment lädt. es ist eine Möglichkeit, dies zu erreichen? das ist mein pageAdapater
public class PagerAdapter extends FragmentPagerAdapter {
private final ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
// private final ArrayList<String> titulos = new ArrayList<String>();
// private int NUM_PAGES =0;
public PagerAdapter(FragmentManager manager,int num_pages) {
super(manager);
// this.NUM_PAGES = num_pages;
}
public void addFragment(Fragment fragment,String title) {
mFragments.add(fragment);
notifyDataSetChanged();
}
@Override
public int getCount() {
//return NUM_PAGES;
return mFragments.size();
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
}
Die obige Methode von Sun hat bei mir nicht funktioniert (vielleicht bei Ihnen), aber ich dachte, ich würde meine Bearbeitung seiner Methode auch teilen. Sehr gute Methode übrigens so!
private boolean _hasLoadedOnce= false; // your boolean field
@Override
public void setUserVisibleHint(boolean isFragmentVisible_) {
super.setUserVisibleHint(true);
if (this.isVisible()) {
// we check that the fragment is becoming visible
if (isFragmentVisible_ && !_hasLoadedOnce) {
new NetCheck().execute();
_hasLoadedOnce = true;
}
}
}
Ich werde hier meine Lösung hinzufügen, da ich auf ein ähnliches Problem gestoßen bin. Meine asynchrone Aufgabe hat keine großen Datenmengen geladen, verhindert jedoch unnötige Netzwerkaufrufe. Folgendes habe ich in mein Fragment eingefügt:
private boolean _hasLoadedOnce= false; // your boolean field
@Override
public void setUserVisibleHint(boolean isFragmentVisible_) {
super.setUserVisibleHint(isVisibleToUser);
if (this.isVisible()) {
// we check that the fragment is becoming visible
if (!isFragmentVisible_ && !_hasLoadedOnce) {
//run your async task here since the user has just focused on your fragment
_hasLoadedOnce = true;
}
}
}
Mit dem obigen Code wird Ihr Fragment geladen, aber Ihre asynchrone Aufgabe wird erst ausgeführt, wenn der Benutzer tatsächlich zum ersten Mal zum Fragment navigiert. Nach der Anzeige wird Ihre asynchrone Aufgabe automatisch zum ersten Mal ausgeführt. Anschließend können Sie über eine Schaltfläche weitere Daten laden oder zum Aktualisieren ziehen. Das obige Fragment befand sich in meinem ViewPager und schien gut zu funktionieren.
Ich komme vielleicht zu spät zur Party, aber hier ist meine Lösung und sie funktioniert wie erwartet. Erstellen Sie in allen untergeordneten Fragmenten eine boolean
-Variable:
private boolean loadFragmentExecuted = false;
erstellen Sie in den untergeordneten Fragmenten eine generische Methode mit dem Namen loadFragment
und verschieben Sie die gesamte Logik, die Sie in onCreateView
hinzugefügt haben, in diese Methode:
public void loadFragment()
{
if(!loadFragmentExecuted)
{
//Add your logic to manipulate the UI or load data etc...
loadFragmentExecuted = true;
}
}
erstellen Sie in Ihrer PageView-Logik die Fragmente dynamisch wie folgt:
//add the fragment
String fragmentName = "com.something." + fragmentId;
//check if the class exists
try
{
Class myFragmentClass = Class.forName(fragmentName);
Fragment myFragment = (Fragment) myFragmentClass.newInstance();
mFragments.add(myFragment);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
catch (InstantiationException e)
{
e.printStackTrace();
}
stellen Sie dann Ihren Pager-Adapter ein und fügen Sie ein Tablayout hinzu:
//set our pager adapter that contains different fragments
mPagerAdapter = new BasePagerAdapter(mFragmentManager, mFragments);
//link the adapter to the viewpager
mViewPager.setAdapter(mPagerAdapter);
//cache fragments
int limit = (mPagerAdapter.getCount() > 0 ? mPagerAdapter.getCount() : 1);
mViewPager.setOffscreenPageLimit(limit);
//add the page listner to the viewPager and link it to the tabLayout
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
//on tab selected select current viewpager item
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
{
@Override
public void onTabSelected(TabLayout.Tab tab)
{
mViewPager.setCurrentItem(tab.getPosition());
//get fragment for the selected tab
Fragment f = mPagerAdapter.getItem(tab.getPosition());
//load the content of the fragment
try
{
Class c = f.getClass();
Method loadFragment = c.getMethod("loadFragment");
loadFragment.invoke(f);
}
catch (IllegalAccessException e){}
catch (InvocationTargetException e){}
catch (NoSuchMethodException e){}
}
@Override
public void onTabUnselected(TabLayout.Tab tab)
{
}
@Override
public void onTabReselected(TabLayout.Tab tab)
{
}
});
Verwenden Sie fragmentStatePageAdapter, wenn Sie viele Seiten haben und diese zerstören möchten, wenn sie nicht sichtbar sind. Es hat ein setMenuVisibility (boolesches menuVisible) implementiert, wenn ein Fragment sichtbar wird. Verwenden Sie dieses.
Leicht modifizierte Version, um potenzielle NPE-Probleme zu beheben, die durch einige nicht vollständig initialisierte Ansichten verursacht wurden
private boolean _hasLoadedOnce= false; // your boolean field
@Override
public void setUserVisibleHint(boolean isFragmentVisible_) {
super.setUserVisibleHint(isVisibleToUser);
if (this.isVisible()) {
// we check that the fragment is becoming visible
if (!isFragmentVisible_ && !_hasLoadedOnce) {
new Handler().post(() -> {
makeAsyncRequest();//do your asyn stuffs
_hasLoadedOnce = true;
});
}
}
}