26

フラグメントとViewPagerを扱うアプリケーションがあります。 ViewPagerに3つのフラグメントがあります。それらの間を切り替えると、常に他の2つのフラグメントがonCreateViewメソッドを呼び出すようになります。 FragmentActivityが作成された場合にのみ、一度だけ行う方法 私はいくつかの質問を読んで、解決策を試しましたが、フラグメントはまだ同じ動作をしています。ここでフラグメントのonCreateView、onCreate、onActivityCreatedが呼び出されるのはなぜですか

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

それはあなたを助けている場合、みんないくつかのコードです:

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

セカンド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; 
    } 
} 

そして第三に1:MapActivityため

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

ログ:次に

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 

何度も何度:

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 

は事前にどうもありがとうございました。

答えて

12

私はAndroidの開発者向けドキュメント上でこの1のためにあなたのアーキテクチャを変更します

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

が、私はいくつかのことを変更します...

1-Iは、この方法で変更します

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

viewPagerの位置に応じて、どのフラグメントを配置するかを決定するこのような場合:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 
super.onCreateView(inflater, container, savedInstanceState); 

SupportFragmentManager ft = getChildFragmentManager().beginTransaction(); 

String tag = ""; 
Fragment fragment = null; 

    switch (mNum) { 
    case 0: 
    fragment = new MyFragmentZero(); 
    tag = FragmentTags.TAG_0; 
    break; 
    case 1: 
    fragment = new MyFragmentOne(); 
    tag = FragmentTags.TAG_3; 
    break; 
    case 2: 
    fragment = new MyFragmentTwo(); 
    tag = FragmentTags.TAG_2; 
    break; 
    default: 
    break; 
    } 

/*OPTIONAL We can pass arguments to the fragments 
Bundle args = new Bundle(); 
args.putInt(Arguments.ARG_POSITION, mNum); 
fragment.setArguments(args);*/ 

//Place the fragment in the container 
ft.replace(R.id.fragment_container fragment, tag); 
ft.commit(); 

//You need a base layout for all fragment and use nested fragments later or you can define the layout for each position(mNum) inside the switch. 
return inflater.inflate(R.layout.fragment_layout_default_for_all_views, container, 
    false); 
} 

このように、優れたアーキテクチャを備えていれば、これはうまくいくはずです。

いずれにしても、viewPagerがどのように異なる位置にフラグメントを移入するのか知っている必要があります。

位置0で開始すると、位置0のフラグメントと位置1のフラグメントが作成されます。

次に、位置1にスワイプすると、2つの位置のフラグメントが作成されるため、異なる位置に作成された3つのフラグメントが作成されます(0,1,2 .. viewPager )。

位置2、最後の1つにスワイプし、最初の位置(0)のフラグメントが破棄されるため、位置2と3のフラグメントが作成されます。

ご不便をおかけしましたら教えてください。乾杯

+0

を説明

mViewPager.setOffscreenPageLimit(2); 

は答えをいただき、ありがとうございます。しかし、それはまさに私がやったことです。問題は、フラグメントが作成され、ジオロケーションを使用するとき、私のアプリが多くの情報をダウンロードしているということです。したがって、1つのフラグメントが作成され、もう1つのフラグメントがビューページャーによって破棄されると、もう一度すべてをダウンロードしなければならず、すばやくスワイプするとアプリがクラッシュします。したがって、ビューページをカスタマイズしてオブジェクトを破壊しないようにすることは不可能ですか? – PAcan

+0

また、フラグメントを破壊しないとは考えていませんが良いアイデアです、それは本当に悪いアプローチです。あなたはメモリ管理の世話をするべきではなく、それを行う... – jpardogo

+3

もう一度すべてをダウンロードしないでください!あなたの活動にこの情報を保存してください(あなたはあなたの活動に必要なものを一度ダウンロードします)。フラグメントをロードする方法を変更し、フラグメントなどのリストを作成しないでください。アダプタからnewInstanceを呼び出すだけです。アンドロイドデベロッパーのドキュメントを注意深く読んで、このコードに従ってください。 MainWindowActivity、MapActivityをMainWindowFragmentに変更すると、MapFragmentも同様に明確になります。 – jpardogo

11

最後に私はそれを理解することができました。 destroyItemメソッドをオーバーライドしてオブジェクトを破棄しないでください。これが誰かにとって有用であることを願っています。

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

これについてもう少し詳細に説明できますか?あなたの破壊方法はどうなっていますか? – Simulant

+0

私は私の答えを編集しました – PAcan

+1

ありがとう〜働く細かい – HenryChuang

12

ViewPagerは、現在のページのいずれかの側に、デフォルトでメモリ1ページを保持します。したがって、現在のページの左右1ページをスワイプすると、それらのページは再作成されません。しかし、1ページ以上を左右にスワイプすると、再びOnCreateView()、OnCreate()と呼ばれるページが再作成されます。

アプリはいくつかのページ3を使用している場合は、あなたが呼び出すことで保持するページ数を増やすことができ、here

+1

これは受け入れられる答えでなければなりません –

関連する問題