26

Ich habe eine App, die sich mit Fragmenten und ViewPager beschäftigt. Ich habe drei Fragmente in einem ViewPager. Wenn Sie zwischen ihnen wechseln, ruft dies immer die anderen beiden Fragmente dazu auf, ihre Methoden onCreateView aufzurufen. Wie mache ich es nur einmal, nur wenn FragmentActivity erstellt wird ??? Ich habe ein paar Fragen gelesen und die Lösungen ausprobiert, aber die Fragmente haben immer noch das gleiche Verhalten.Warum heißt OnCreateView, onCreate, onActivityCreated des Fragments

ListFragment onCreate called twice
onCreate() and onCreateView() invokes a lot more than required (Fragments)

Hier ist ein Code, wenn es Ihnen hilft, Jungs:

MainActivity:

public class StartingActivity extends FragmentActivity implements View.OnClickListener { 
ViewPager viewPager; 
    CirclePageIndicator pageIndicator; 

    Button discount; 
    Button qrCode; 
    Button pay; 
    TabHost tabHost; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.starting_layout); 
     viewPager = (ViewPager) findViewById(R.id.pager); 

     if (savedInstanceState == null) { 

      Fragment firstPage = Fragment.instantiate(this, FindTovarFragment.class.getName()); 
      Fragment secondPage = Fragment.instantiate(this, MainWindowActivity.class.getName()); 
      Fragment thirdPage = Fragment.instantiate(this, MapActivity.class.getName()); 

      if ((firstPage != null && !firstPage.isDetached())|| (secondPage != null && !secondPage.isDetached()) || (thirdPage != null && !thirdPage.isDetached())) { 

      List<Fragment> viewPagerFragments = new ArrayList<Fragment>(); 
      viewPagerFragments.add(firstPage); 
      viewPagerFragments.add(secondPage); 
      viewPagerFragments.add(thirdPage); 


      PageAdapter pageAdapter = new PageAdapter(getSupportFragmentManager(), viewPagerFragments); 

      viewPager.setAdapter(pageAdapter); 

      pageIndicator = (CirclePageIndicator) findViewById(R.id.circle); 
      pageIndicator.setViewPager(viewPager); 
      pageIndicator.setCurrentItem(pageAdapter.getCount() - 2); 
      } 
     } 

} 

MapActivity:

public class MapActivity extends Fragment implements OnMyLocationListener { 

    //Тэг для логов 
    private static final String TAG = "MapActivity"; 
    List<Address> addressList; 
    private static final String STRING_LOCATION = ""; 

    ArrayList<TorgCentr> randomTorgCentr; 
    ArrayList<String> torgCentrNames; 

    Context context; 
    AutoCompleteTextView searchTorgCentr; 
    OverlayManager overlayManager; 
    MapController mapController; 
    TextView textView; 
    double longitude; 
    double latitude; 
    double itemLongitude; 
    double itemLatitude; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     Log.d(TAG, "MapActivity onCreateView"); 


     View view = (LinearLayout) inflater.inflate(R.layout.map_layout, container, false); 
     final MapView mapView = (MapView) view.findViewById(R.id.map); 
     textView = (TextView) view.findViewById(R.id.searchlocation); 
     searchTorgCentr = (AutoCompleteTextView) view.findViewById(R.id.autoCompleteTextView); 

     mapView.showBuiltInScreenButtons(true); 
     mapController = mapView.getMapController(); 
     context = getActivity(); 
     return view; 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Log.d(TAG, "MapActivity onCreate"); 

    } 

    public void onActivityCreated(Bundle savedInstanceState) { 
     Log.d(TAG, "MapActivity onActivityCreated"); 
     context = getActivity(); 

     SetRightMapDisplayAddress rightMapDisplayAddress = new SetRightMapDisplayAddress(); 
     rightMapDisplayAddress.execute(STRING_LOCATION); 

     DownloadSuperMarketsArray superMarketsArray = new DownloadSuperMarketsArray(); 
     superMarketsArray.execute(); 

     overlayManager = mapController.getOverlayManager(); 
     overlayManager.getMyLocation().setEnabled(false); 

     super.onActivityCreated(savedInstanceState); 
    } 

Zweite Frag ment:

public class MainWindowActivity extends Fragment { 

    private static final String TAG = "MainWindowActivity"; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     Log.d(TAG, "MainWindowActivity onCreateView"); 
     View view = (RelativeLayout) inflater.inflate(R.layout.main_window_layout, container, false); 
     if (container == null) { 
      return null; 
     } 
     return view; 
    } 
} 

Und der dritte:

public class FindTovarFragment extends Fragment { 

    private static final String TAG= "FindTovarFragment"; 

    Context context; 
    ArrayList<Category> categories; 
    Spinner categoryContainer; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     Log.d(TAG, "FindTovarFragment onCreateView"); 

     View view = (LinearLayout) inflater.inflate(R.layout.find_tovar_main_layout, container, false); 
     categoryContainer = (Spinner) view.findViewById(R.id.category); 

     return view; 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     Log.d(TAG, "FindTovarFragment onActivityCreated"); 
     DownloadCategory downloadCategory = new DownloadCategory(); 
     downloadCategory.execute(); 
    } 

Logs für MapActivity:

06-20 11:06:37.709: DEBUG/MapActivity(1290): MapActivity onCreate 
06-20 11:06:37.709: DEBUG/MapActivity(1290): MapActivity onCreateView 
06-20 11:06:38.509: DEBUG/MapActivity(1290): MapActivity onActivityCreated 

Dann immer wieder:

06-20 11:07:53.239: DEBUG/MapActivity(1290): MapActivity onCreate 
06-20 11:07:53.239: DEBUG/MapActivity(1290): MapActivity onCreateView 
06-20 11:07:53.429: DEBUG/MapActivity(1290): MapActivity onActivityCreated 
06-20 11:08:23.029: DEBUG/MapActivity(1290): MapActivity onCreate 
06-20 11:08:23.039: DEBUG/MapActivity(1290): MapActivity onCreateView 
06-20 11:08:23.269: DEBUG/MapActivity(1290): MapActivity onActivityCreated 

Vielen Dank im Voraus .

Antwort

12

Ich würde Ihre Architektur für diesen einen auf der Android-Entwicklerdokumentation ändern:

http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html

aber ich würde ein paar Dinge ändern ...

1-Ich würde dieses Verfahren ändern:

/** 
    * The Fragment's UI is just a simple text view showing its 
    * instance number. 
    */ 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.fragment_pager_list, container, false); 
     View tv = v.findViewById(R.id.text); 
     ((TextView)tv).setText("Fragment #" + mNum); 
     return v; 
    } 

Für so etwas, wo wir entscheiden, welches Fragment Sie befüllen, abhängig von der Position des viewPagers:

So haben Sie eine gute Architektur und sobald es funktioniert, sollte dies in Ordnung sein.

Wie auch immer Sie wissen müssen, wie der viewPager das Fragment in den verschiedenen Positionen bevölkert.

Wenn Sie an der Position 0 beginnen, wird das Fragment an der Position 0 und an der Position 1 erstellt.

Wenn Sie dann an die Position 1 wischen, wird das Fragment an der Position 2 erstellt, so dass Sie jetzt die drei Fragmente an den verschiedenen Positionen erstellt haben (0,1,2..nur vorausgesetzt, Sie haben nur 3 Seiten auf dem viewPager)).

Wir wischen auf die Position 2, die letzte, und das Fragment auf der ersten Position (0) wird zerstört, also haben wir jetzt die Fragmente auf den Positionen 2 und 3.

Ich hoffe, es hat geholfen und lassen Sie mich wissen, wenn Sie ein Problem haben. Prost

+0

Dank für die Antwort danken. Aber es ist genau das, was ich getan habe. Das Problem ist, dass meine App eine Menge Informationen herunterlädt, wenn die Fragmente erstellt werden und Geolocation verwendet. Wenn also ein Fragment erstellt wird und das andere von einem Viewpager zerstört wird, muss es alles noch einmal herunterladen und die App stürzt ab, wenn Sie schnell wischen. Ist es also nicht möglich, den Viewpager so anzupassen, dass Objekte nicht zerstört werden? – PAcan

+0

Auch ich denke nicht, die Fragmente nicht zu zerstören ist eine gute Idee, es ist wirklich schlechte Ansatz. Sie sollten sich um die Speicherverwaltung kümmern und das nicht tun ... – jpardogo

+3

Bitte nicht alles nochmal herunterladen! Speichern Sie diese Informationen in Ihrer Aktivität (Sie laden einfach alles herunter, was Sie für Ihre Aktivität benötigen) und kommunizieren Sie über Schnittstellen mit dem Fragment. Und ändern Sie die Art und Weise, wie Sie die Fragmente laden, erstellen Sie keine Liste von Fragment oder so etwas nur NewInstance aus dem Adapter. Bitte lesen Sie die Android-Entwickler-Dokumentation sorgfältig und folgen Sie diesem Code, ich denke, es ist die beste Idee. Umbenennen von MainWindowActivity, MapActivity zu MainWindowFragment, MapFragment wäre auch klarer. – jpardogo

11

Endlich konnte ich es herausfinden. Sie müssen nur die destroyItem-Methode überschreiben, damit Objekte nicht zerstört werden. Hoffe, das wird für jemanden nützlich sein.

@Override 
public void destroyItem(ViewGroup container, int position, Object object) { 
    Log.d(TAG, "destroy!"); 
} 
+0

Könnten Sie das ein bisschen mehr im Detail erklären? Wie sieht deine Zerstörungsmethode aus? – Simulant

+0

Ich habe meine Antwort bearbeitet – PAcan

+1

Danke ~ Arbeit gut – HenryChuang

12

ViewPager im Speicher 1 Seite standardmäßig behalten, zu beiden Seiten der aktuellen Seite. Es würde also diese Seiten nicht neu erstellen, wenn Sie 1 Seite links/rechts von der aktuellen Seite wischen. Wenn Sie jedoch mehr als 1 Seite nach links/rechts wischen, wird diese Seite erneut erstellt, daher OnCreateView(), OnCreate().

Wenn App paar Seiten 3 verwendet, können Sie die Anzahl der Seiten erhöhen durch den Aufruf, behalten

mViewPager.setOffscreenPageLimit(2); 

Beschrieben here

+1

Dies sollte die akzeptierte Antwort sein –