在开发中ViewPager+fragment,包括缓存pager或者fragment中一些问题,什么时候该缓存销毁page,什么时候缓存销毁fragment问题
FragmentPagerAdapter,FragmentStatePagerAdapter的区别和适用场景
FragmentPagerAdapter
1、通过offscreenPageLimit来控制page container的cache数量 n*2+1;
2、当加载的page超出cache count会用FragmentManager来释放fragment
3、被释放的fragment实际上不会被完全回收,因为没有调用onDestory(),当再次回到这个page时也没有调用onCreate();
4、当fragment被显示在屏幕上时,setUserVisibleHint为true,不显示时为false.
适用于:
page是固定的,并且数量比较少,因为fragment不会被完全回收
FragmentStatePagerAdapter
其他三点都一样,不同的是
被释放的fragment会被完全回收,调用了onDestory()的方法;
适用于:
比较多的fragment,保证回收,清理内存
1、首先明确Fragment的生命周期
如果用ViewPager+fragment,首先应该明确fragment的生命周期,这个fragment什么时候开始创建,什么时候创建完成,什么时候创建view,什么时候可以加载数据。
几个重要容易模糊的生命周期
1、onAttach() 当一个fragment第一次绑定到它所属的activity中
/**
* Called when a fragment is first attached to its activity.
* {@link #onCreate(Bundle)} will be called after this.
* <p>Deprecated. See {@link #onAttach(Context)}.
*/
@Deprecated
public void onAttach(Activity activity) {
mCalled = true;
}
2、onCreate()它所属的activity正在创建中,并没有创建完成
/**
* Called to do initial creation of a fragment. This is called after
* {@link #onAttach(Activity)} and before
* {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
*
* <p>Note that this can be called while the fragment's activity is
* still in the process of being created. As such, you can not rely
* on things like the activity's content view hierarchy being initialized
* at this point. If you want to do work once the activity itself is
* created, see {@link #onActivityCreated(Bundle)}.
*
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
public void onCreate(@Nullable Bundle savedInstanceState) {
mCalled = true;
}
3、onCreateView():可以把fragment的布局填充到view中,返回fragment的UI布局。
/**
* Called to have the fragment instantiate its user interface view.
* This is optional, and non-graphical fragments can return null (which
* is the default implementation). This will be called between
* {@link #onCreate(Bundle)} and {@link #onActivityCreated(Bundle)}.
*
* <p>If you return a View from here, you will later be called in
* {@link #onDestroyView} when the view is being released.
*
* @param inflater The LayoutInflater object that can be used to inflate
* any views in the fragment,
* @param container If non-null, this is the parent view that the fragment's
* UI should be attached to. The fragment should not add the view itself,
* but this can be used to generate the LayoutParams of the view.
* @param savedInstanceState If non-null, this fragment is being re-constructed
* from a previous saved state as given here.
*
* @return Return the View for the fragment's UI, or null.
*/
@Nullable
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return null;
}
4、onActivityCreated():这时候activity创建完成,并且fragment布局已经填充进去。
/**
* Called when the fragment's activity has been created and this
* fragment's view hierarchy instantiated. It can be used to do final
* initialization once these pieces are in place, such as retrieving
* views or restoring state. It is also useful for fragments that use
* {@link #setRetainInstance(boolean)} to retain their instance,
* as this callback tells the fragment when it is fully associated with
* the new activity instance. This is called after {@link #onCreateView}
* and before {@link #onViewStateRestored(Bundle)}.
*
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
mCalled = true;
}
5、onDestroyView:销毁当前的view也就是填充的布局
/**
* Called when the view previously created by {@link #onCreateView} has
* been detached from the fragment. The next time the fragment needs
* to be displayed, a new view will be created. This is called
* after {@link #onStop()} and before {@link #onDestroy()}. It is called
* <em>regardless</em> of whether {@link #onCreateView} returned a
* non-null view. Internally it is called after the view's state has
* been saved but before it has been removed from its parent.
*/
public void onDestroyView() {
mCalled = true;
}
6、onDestroy():销毁当前的fragment
/**
* Called when the fragment is no longer in use. This is called
* after {@link #onStop()} and before {@link #onDetach()}.
*/
public void onDestroy() {
mCalled = true;
//Log.v("foo", "onDestroy: mCheckedForLoaderManager=" + mCheckedForLoaderManager
// + " mLoaderManager=" + mLoaderManager);
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
}
}
2、ViewPager中的适配器使用FragmentPagerAdapter
package com.example.yu.viewpager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import com.example.yu.baseactivity.R;
import com.example.yu.viewpager.fragment.Fragment1;
import com.example.yu.viewpager.fragment.Fragment2;
import com.example.yu.viewpager.fragment.Fragment3;
import com.example.yu.viewpager.fragment.Fragment4;
import com.example.yu.viewpager.fragment.Fragment5;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends FragmentActivity {
private ViewPager viewPager;
private MyFragemtAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewPager);
List<Fragment> fragments = new ArrayList<Fragment>();
fragments.add(new Fragment1());
fragments.add(new Fragment2());
fragments.add(new Fragment3());
fragments.add(new Fragment4());
fragments.add(new Fragment5());
adapter = new MyFragemtAdapter(getSupportFragmentManager(), fragments);
//设置缓存page的个数 2*n+1;
viewPager.setOffscreenPageLimit(1);
viewPager.setAdapter(adapter);
}
class MyFragemtAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragments;
public MyFragemtAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
}
}
Fragment1示例代码如下(其他四个也都一样)
package com.example.yu.viewpager.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.yu.baseactivity.R;
/**
* Created by yu on 2016/6/12.
*/
public class Fragment1 extends Fragment {
public static final String TAG = "Fragment1";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment1, container, false);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.i(TAG, "fragment is onDestroyView()");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "fragment is onDestroy()");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "fragment is onCreate()");
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i(TAG, "fragment is onActivityCreated()");
}
}
3、ViewPager中的适配器使用FragmentStatePagerAdapter
其他代码都不动,只修改适配器类型为FragmentStatePagerAdapter
class MyFragemtAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragments;
public MyFragemtAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
}
从Log日志分析