26

У меня есть приложение, которое касается фрагментов и ViewPager. У меня есть три фрагмента в ViewPager. Когда вы переключаетесь между ними, он всегда заставляет другие два фрагмента вызывать свои методы 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; 
    } 
} 

И третий один:

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

Журналы для 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 

Затем снова и снова:

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:

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

, но я хотел бы изменить некоторые вещи ...

1-я изменил бы этот метод:

/** 
    * 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 позиции, так что теперь у вас есть три фрагмента, созданных на разных позициях (0,1,2 .. если у вас есть только 3 страницы на viewPager).

Мы проведите пальцем в положение 2, последнее, а фрагмент в первой позиции (0) уничтожим, поэтому у нас есть фрагменты на позициях 2 и 3.

Я надеюсь, что это помогло и сообщит мне, если у вас возникли проблемы. Cheers

+0

Спасибо за ответ. Но это именно то, что я сделал. Проблема в том, что мое приложение загружает много информации, когда фрагменты создаются и использует геолокацию. Поэтому, когда один фрагмент создается, а другой уничтожается с помощью viewpager, он должен снова загружать все, и приложение падает, если вы быстро проведите по экрану. Так что невозможно настроить просмотрщик, чтобы он не уничтожал объекты? – PAcan

+0

Также я не думаю, что не уничтожать фрагменты - это хорошая идея, это действительно плохой подход. Вы должны позаботиться об управлении памятью и не делать этого ... – jpardogo

+3

Пожалуйста, не загружайте все снова! Храните эту информацию в своей деятельности (вы загружаете все, что вам нужно, только один раз) и общаетесь с ней через интерфейсы, образующие фрагмент. И измените способ загрузки фрагментов, не создавайте список фрагментов или что-то в этом роде, просто вызывайте newInstance из адаптера. Пожалуйста, внимательно прочитайте документацию разработчиков Android и следуйте этому коду, я думаю, что это лучшая идея. Переименуйте 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, вы можете увеличить количество страниц, чтобы сохранить с помощью вызова,

mViewPager.setOffscreenPageLimit(2); 

Описан here

+1

Это должен быть принятый ответ –

Смежные вопросы