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

二破片换货:

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 ..假设您在viewPager上只有3个页面)。

我们滑动到位置2,最后一个位置,并且第一个位置(0)上的碎片被破坏,所以我们现在在位置2和3上有碎片。

我希望它帮助,让我知道你是否有任何问题。欢呼声

+0

谢谢你的答案。但这正是我所做的。问题是,我的应用程序正在下载大量的信息,当碎片被创建并使用地理定位。所以当一个片段被创建并且另一个片段被viewpager销毁时,它必须再次下载一切,并且如果快速滑动,则应用程序崩溃。所以不可能自定义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

这应该是公认的答案 –

相关问题