本博客部分内容是来自http://blog.csdn.net/dreamzml/article/details/9951577
先贴下别人总结的
FragmentPagerAdapter
- getItem()
- 该类中新增的一个虚函数。函数的目的为生成新的 Fragment 对象。重载该函数时需要注意这一点。在需要时,该函数将被 instantiateItem() 所调用。
- 如果需要向 Fragment 对象传递相对静态的数据时,我们一般通过 Fragment.setArguments() 来进行,这部分代码应当放到 getItem()。它们只会在新生成 Fragment 对象时执行一遍。
- 如果需要在生成 Fragment 对象后,将数据集里面一些动态的数据传递给该 Fragment,那么,这部分代码不适合放到 getItem() 中。因为当数据集发生变化时,往往对应的 Fragment 已经生成,如果传递数据部分代码放到了 getItem() 中,这部分代码将不会被调用。这也是为什么很多人发现调用 PagerAdapter.notifyDataSetChanged() 后,getItem() 没有被调用的一个原因。
- instantiateItem()
- 函数中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的,新的对象将被 FragmentTransation.add()。
- FragmentPagerAdapter 会将所有生成的 Fragment 对象通过 FragmentManager 保存起来备用,以后需要该 Fragment 时,都会从 FragmentManager 读取,而不会再次调用 getItem() 方法。
- 如果需要在生成 Fragment 对象后,将数据集中的一些数据传递给该 Fragment,这部分代码应该放到这个函数的重载里。在我们继承的子类中,重载该函数,并调用 FragmentPagerAdapter.instantiateItem() 取得该函数返回 Fragment 对象,然后,我们该 Fragment 对象中对应的方法,将数据传递过去,然后返回该对象。
- 否则,如果将这部分传递数据的代码放到 getItem()中,在 PagerAdapter.notifyDataSetChanged() 后,这部分数据设置代码将不会被调用。
- destroyItem()
- 该函数被调用后,会对 Fragment 进行 FragmentTransaction.detach()。这里不是 remove(),只是 detach(),因此 Fragment 还在 FragmentManager 管理中,Fragment 所占用的资源不会被释放。
1.首先在MainActivity中为ViewPaper设置FragmentPagerAdapter
2..FragmentPagerAdapter的内容如下
<span style="font-size:18px;">public class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
Log.i(TAG, "-----进入 MyPagerAdapter(FragmentManager fm)--->");
}
private final String[] titles = { "聊天", "发现", "通讯录","我"};
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public int getCount() {
return titles.length;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
if (chatFragment == null) {
chatFragment = new ChatFragment();
Log.i(TAG, "-----getItem()--生成ChatFragment->");
}
return chatFragment;
case 1:
if (foundFragment == null) {
foundFragment = new FoundFragment();
Log.i(TAG, "-----getItem()--生成foundFragment->");
}
return foundFragment;
case 2:
if (contactsFragment == null) {
contactsFragment = new ContactsFragment();
Log.i(TAG, "-----getItem()--生成contactsFragment->");
}
return contactsFragment;
case 3:
if (myFragment == null) {
myFragment = new MyFragment();
Log.i(TAG, "-----getItem()--生成myFragment->");
}
return myFragment;
default:
return null;
}
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// TODO Auto-generated method stub
Log.i(TAG, "-----instantiateItem()-->" + titles[position]);
return super.instantiateItem(container, position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// TODO Auto-generated method stub
Log.i(TAG, "-----destroyItem()-销毁->" + titles[position]);
super.destroyItem(container, position, object);
}
}</span>
3.四个Fragment内容类似,就只贴出ChatFragment
<span style="font-size:18px;">package com.eeb.learnactionbar;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.FrameLayout.LayoutParams;
public class ChatFragment extends Fragment {
public final static String TAG = "TAG";
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
Log.i(TAG, "-----ChatFragment---------onAttach--->");
}
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Log.i(TAG, "-----ChatFragment---------onCreate--->");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i(TAG, "-----ChatFragment---------onCreateView--->");
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
FrameLayout fl = new FrameLayout(getActivity());
fl.setLayoutParams(params);
DisplayMetrics dm = getResources().getDisplayMetrics();
final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, dm);
TextView v = new TextView(getActivity());
params.setMargins(margin, margin, margin, margin);
v.setLayoutParams(params);
v.setLayoutParams(params);
v.setGravity(Gravity.CENTER);
v.setText(getArguments().getString("title"));
v.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, dm));
fl.addView(v);
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent(getActivity(), TestActiity.class));
}
});
return fl;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "-----ChatFragment---------onActivityCreated--->");
}
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewStateRestored(savedInstanceState);
Log.i(TAG, "-----ChatFragment---------onViewStateRestored--->");
}
@Override
public void onStart() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onStart--->");
super.onStart();
}
@Override
public void onResume() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onResume--->");
super.onResume();
}
@Override
public void onPause() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onPause--->");
super.onPause();
}
@Override
public void onStop() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onStop--->");
super.onStop();
}
@Override
public void onDestroyView() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onDestroyView--->");
super.onDestroyView();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onDestroy--->");
super.onDestroy();
}
@Override
public void onDetach() {
// TODO Auto-generated method stub
Log.i(TAG, "-----ChatFragment---------onDetach--->");
super.onDetach();
}
}
</span>
运行程序显示如下
FragmentPagerAdapter默认是先预加载一页的,比如显示了第1页,就会把第2页也加载了,先调用FragmentPagerAdapter的构造方法 MyPagerAdapter(FragmentManager fm),再调用instantiateItem(ViewGroup container, int position) 函数中判断一下要生成的 Fragment 是否已经生成过了,如果生成过了,就使用旧的,旧的将被 Fragment.attach();如果没有,就调用 getItem() 生成一个新的,然后再调用ChatFragment与foundFragment的生命周期
当成第1页滑到第2页时,也是先去预加载第3页
从第2页滑到第3页。会先调用FragmentPagerAdapter的destroyItem(ViewGroup container, int position, Object object)把第1页的view给销毁了执行ChatFragment的onPause(),onStop(),onDestroyview(),注意,没有执行onDestroy(),然后再预加载第4页的MyFragment的生命周期。
同样滑到第4页时候,就会把第2页的view给销毁了
从第4页回到第3页,预加载第2页,此时发现调用instantiateItem(ViewGroup container, int position) 函数时,因为FoundFragment已经生成过了,所以不会再去调用getItem()方法了,再加载其生命周期
同样从第3页回到第2页,先把
回到第1页
按第一页的聊天,启动到TestActivity
按物理返回键
可见Fragment的生命周期是紧跟的主activity
按返回退出程序
在第1页中点击通讯录到第3页
在第1页中点击我到第4页
最后,验证了最上面的那位哥的结论。
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.v4.app;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
/**
* Implementation of {@link android.support.v4.view.PagerAdapter} that
* represents each page as a {@link Fragment} that is persistently
* kept in the fragment manager as long as the user can return to the page.
*
* <p>This version of the pager is best for use when there are a handful of
* typically more static fragments to be paged through, such as a set of tabs.
* The fragment of each page the user visits will be kept in memory, though its
* view hierarchy may be destroyed when not visible. This can result in using
* a significant amount of memory since fragment instances can hold on to an
* arbitrary amount of state. For larger sets of pages, consider
* {@link FragmentStatePagerAdapter}.
*
* <p>When using FragmentPagerAdapter the host ViewPager must have a
* valid ID set.</p>
*
* <p>Subclasses only need to implement {@link #getItem(int)}
* and {@link #getCount()} to have a working adapter.
*
* <p>Here is an example implementation of a pager containing fragments of
* lists:
*
* {@sample development/samples/Support4Demos/src/com/example/android/supportv4/app/FragmentPagerSupport.java
* complete}
*
* <p>The <code>R.layout.fragment_pager</code> resource of the top-level fragment is:
*
* {@sample development/samples/Support4Demos/res/layout/fragment_pager.xml
* complete}
*
* <p>The <code>R.layout.fragment_pager_list</code> resource containing each
* individual fragment's layout is:
*
* {@sample development/samples/Support4Demos/res/layout/fragment_pager_list.xml
* complete}
*/
public abstract class FragmentPagerAdapter extends PagerAdapter {
private static final String TAG = "FragmentPagerAdapter";
private static final boolean DEBUG = false;
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurTransaction = null;
private Fragment mCurrentPrimaryItem = null;
public FragmentPagerAdapter(FragmentManager fm) {
mFragmentManager = fm;
}
/**
* Return the Fragment associated with a specified position.
*/
public abstract Fragment getItem(int position);
@Override
public void startUpdate(ViewGroup container) {
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
final long itemId = getItemId(position);
// Do we already have this fragment?
String name = makeFragmentName(container.getId(), itemId);
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
mCurTransaction.attach(fragment);
} else {
fragment = getItem(position);
if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
mCurTransaction.add(container.getId(), fragment,
makeFragmentName(container.getId(), itemId));
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
+ " v=" + ((Fragment)object).getView());
mCurTransaction.detach((Fragment)object);
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}
@Override
public void finishUpdate(ViewGroup container) {
if (mCurTransaction != null) {
mCurTransaction.commitAllowingStateLoss();
mCurTransaction = null;
mFragmentManager.executePendingTransactions();
}
}
@Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment)object).getView() == view;
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
/**
* Return a unique identifier for the item at the given position.
*
* <p>The default implementation returns the given position.
* Subclasses should override this method if the positions of items can change.</p>
*
* @param position Position within this adapter
* @return Unique identifier for the item at position
*/
public long getItemId(int position) {
return position;
}
private static String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
}