请看我的另外一篇文章,更好《Fragment管理的工具类》
有些时候我们都需要Fragment的延时加载,这样可以减轻多个fragment在初始化时的切换的卡顿。
多个fragment的使用方式有两种,一个是在ViewPager中使用,另一个是通过add()方法添加到Activity,然后通过show(),和hide()方法控制Fragment的显示。
其实要做到延时就是继承Fragment,然后修改它的setUserVisibleHint方法就行了。根据boolean值判断是不是可见就行了
下面就是他的代码
package com.yky.fragementtest.fragmentdao;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by Administrator on 2015/4/28.
*/
public abstract class AbsFragment extends android.support.v4.app.Fragment {
protected View mRootView;
protected byte isInitState = 0x00; //是否已加载(0x00 未加载 , 0x01 加载中 , 0x02 加载完成)
private Handler mPriHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1: //可见
onVisiable();
break;
case 2: //不可见
onInvisiable();
break;
case 3: //第一次加载
if (isInitState == 0x00) {
isInitState = 0x01;
onFirstVisiableLoad();
isInitState = 0x02;
mPriHandler.sendEmptyMessage(1);
}
break;
}
}
};
protected abstract int getLayoutId();
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.i("fragmentState", "onCreateView " + getClass().getName());
mRootView = inflater.inflate(getLayoutId(), container, false);
return mRootView;
}
public static final void changeFragment(android.support.v4.app.FragmentManager fmanager, AbsFragment hideFragment, AbsFragment showFragment) {
if (showFragment.isVisible())
return;
FragmentTransaction transaction = fmanager.beginTransaction();
transaction.hide(hideFragment);
transaction.show(showFragment);
hideFragment.setUserVisibleHint(false);
showFragment.setUserVisibleHint(true);
transaction.commitAllowingStateLoss();
}
//第一次可见加载
protected abstract void onFirstVisiableLoad();
//当可见
protected abstract void onVisiable();
//当不可见
protected abstract void onInvisiable();
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
//如果还没有调用onFirstVisiableLoad,是不会调用可见和不可见的方法的
if (isVisibleToUser) {
if (isInitState == 0x02) {
mPriHandler.sendEmptyMessage(1);
} else if (isInitState == 0x00) {
mPriHandler.sendEmptyMessageDelayed(3, 1000);//延迟0.5秒加载
}
} else {
if (isInitState == 0x02) {
mPriHandler.sendEmptyMessage(2);
} else {
mPriHandler.removeMessages(3);
}
}
}
public View findViewById(int id) {
if (mRootView == null) {
return null;
}
return mRootView.findViewById(id);
}
}
还要注意一点就是如果使用ViewPager的话,你的适配器是继承FragmentPageAdapter的话,记住要修改他的destroyItem方法,因为如果没有修改的话,ViewPager会销毁隐藏的Fragment,再显示时就会重新调用onCreateView方法,这样延时就失效了。
修改的方法
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// super.destroyItem(container, position, object);
}
这样就可以在ViewPager使用。
但是如果你是用另一种方式(通过add()方法添加到Activity,然后通过show(),和hide()方法控制Fragment的显示),你就会发现这样是没有用的,因为
setUserVisibleHint
根本就没有被调用,本来一开始我以为那个方法是Activity自动调用的,但是研究了一下FragmentPageAdapter的方法后才知道,原来这个方法是在Adapter自动使用的。
下面是FragmentPageAdapter的部分代码
@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 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;
}
}
可以看到,原来是Adapter调用的。
这样,解决方法就是我们要在show或hide时自己调用这个方法,好了下面就是代码
package com.yky.fragementtest;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import com.yky.fragementtest.fragmentdao.AbsFragment;
/**
* Created by Administrator on 2015/4/28.
*/
public class Main2Activity extends ActionBarActivity implements View.OnClickListener {
private FragmentOne one;
private FragmentTwo tow;
private FragmentThree three;
FragmentManager fmanager;
FragmentPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2_fragment);
fmanager = getSupportFragmentManager();
one = new FragmentOne();
tow = new FragmentTwo();
FragmentTransaction transaction = fmanager.beginTransaction();
transaction.add(R.id.container, one, "one");
transaction.add(R.id.container, tow, "two");
transaction.hide(tow);
transaction.show(one);
tow.setUserVisibleHint(false);
one.setUserVisibleHint(true);
transaction.commitAllowingStateLoss();
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
changeFragment(fmanager, tow, one);
break;
case R.id.button2:
changeFragment(fmanager, one, tow);
break;
}
}
public void changeFragment(android.support.v4.app.FragmentManager fmanager, AbsFragment hideFragment, AbsFragment showFragment) {
if (showFragment.isVisible())
return;
FragmentTransaction transaction = fmanager.beginTransaction();
transaction.hide(hideFragment);
transaction.show(showFragment);
hideFragment.setUserVisibleHint(false);
showFragment.setUserVisibleHint(true);
transaction.commitAllowingStateLoss();
}
}
demo下载地址
http://download.youkuaiyun.com/detail/a1a1a1a1s/8643483