为啥会调用fragment的onCreateView、onCreate、onActivityCreated
Posted
技术标签:
【中文标题】为啥会调用fragment的onCreateView、onCreate、onActivityCreated【英文标题】:Why does the fragment's onCreateView, onCreate, onActivityCreated are called为什么会调用fragment的onCreateView、onCreate、onActivityCreated 【发布时间】:2013-06-16 17:03:27 【问题描述】:我有一个处理片段和 ViewPager 的应用程序。我在 ViewPager 中有三个片段。当您在它们之间切换时,它总是会导致其他两个片段调用它们的 onCreateView 方法。如何只做一次,只有在创建 FragmentActivity 时才做??? 我已经阅读了一些问题并尝试了解决方案,但片段仍然具有相同的行为。
ListFragment onCreate called twiceonCreate() and onCreateView() invokes a lot more than required (Fragments)
这里有一些代码,如果对你们有帮助的话,伙计们:
主活动:
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);
地图活动:
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
非常感谢您。
【问题讨论】:
【参考方案1】:ViewPager 默认在内存中保留 1 页,到当前页的任一侧。因此,在当前页面向左/向右滑动 1 页时,它不会重新创建这些页面。但是当向左/向右滑动超过 1 个页面时,它会再次重新创建这些页面,因此称为 OnCreateView()、OnCreate()。
如果app使用的页面数很少3,可以通过调用增加页面保留数,
mViewPager.setOffscreenPageLimit(2);
描述为here
【讨论】:
【参考方案2】:我会在 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 上的片段。
希望对您有所帮助,如果您有任何问题,请告诉我。干杯
【讨论】:
感谢您的回答。但这正是我所做的。问题是我的应用程序在创建片段并使用地理定位时下载了大量信息。因此,当一个片段被创建而另一个片段被 viewpager 销毁时,它必须再次下载所有内容,如果您快速滑动,应用程序将崩溃。那么是不是不能自定义viewpager,这样就不会破坏对象了?? 另外我不认为不破坏碎片是一个好主意,这是一个非常糟糕的方法。您应该注意内存管理,而不是这样做...... 请不要再次下载所有内容!将此信息存储在您的活动中(您只需下载一次活动所需的任何内容)并通过片段形式的接口与其通信。并更改加载片段的方式,不要创建片段列表或类似的东西,只需从适配器调用 newInstance。请仔细阅读 android 开发人员文档并遵循此代码,我认为这是最好的主意。将 MainWindowActivity、MapActivity 重命名为 MainWindowFragment,MapFragment 也会更清晰。 这里是:developer.android.com/training/basics/fragments/…【参考方案3】:我终于弄明白了。只需要重写destroyItem 方法,这样它就不会破坏对象。希望这对某人有用。
@Override
public void destroyItem(ViewGroup container, int position, Object object)
Log.d(TAG, "destroy!");
【讨论】:
你能详细解释一下吗?你的销毁方法是什么样的?以上是关于为啥会调用fragment的onCreateView、onCreate、onActivityCreated的主要内容,如果未能解决你的问题,请参考以下文章
为啥显示Fragment1之前会调用Fragment2的onCreateView
为啥android fragment 不调用 oncreateview方法
Fragment和Activity生命周期以及横竖屏切换对生命周期的影响
AsyncTask 在 ViewPager 的每个页面上运行