【Android策略决】Fragment实例化及通过setArguments解决 android.support.v4.app.Fragment$InstantiationException

Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.storm.durian.f.c: make sure class name exists, is public, and has an empty constructor that is public

翻译一下就是: 不能够实例化Fragment,请确定类名存在且是公共类,并且有一个公共的构造函数

首先这个问题不必现,出现了有可能导致应用页面崩溃

先看一下导致这个问题的代码

 public static FavoriteAndFansFragment newInstance(String uid, boolean isSelfUser, int type) {
		FavoriteAndFansFragment f = new FavoriteAndFansFragment(uid, isSelfUser, type);
		return f;
	}
	
 public FavoriteAndFansFragment (String uid, boolean isSelfUser, int type) {
		super();
	    this.uid = uid;
		this.isSelfUser = isSelfUser;
		this.type = type;
		if (type == 0) {
		    url = UrlContainer.USER_FOLLOWER_URL;
		}else{
		    url = UrlContainer.USER_FANS_URL;
		}
	}

	/**
	 * When creating, retrieve this instance's number from its arguments.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
	}


再看一下优化后的代码

  /**
	 * Create a new instance of Fragment, providing para as an
	 * argument.
	 */
 public static FavoriteAndFansFragment newInstance(String uid, boolean isSelfUser, int type) {
	FavoriteAndFansFragment f = new FavoriteAndFansFragment();
        Bundle args = new Bundle();
        args.putString("uid", uid);
        args.putBoolean("isSelfUser", isSelfUser);
        args.putInt("type", type);
        f.setArguments(args);
        return f;
	}
	
	/**
	 * When creating, retrieve this instance's para from its arguments.
	 */
	@Override
 public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle != null) {
            uid = bundle.getString("uid");
            isSelfUser = bundle.getBoolean("isSelfUser");
            type = bundle.getInt("type");
            if (type == 0) {
                url = UrlContainer.USER_FOLLOWER_URL;
            } else {
                url = UrlContainer.USER_FANS_URL;
            }
        }

    }

分析:

1、官方推荐Fragment.setArguments(Bundle bundle)这种方式来传递参数,而不推荐通过构造方法直接来传递参数,why?

2、当一个fragment重新创建的时候,系统会再次调用 Fragment中的默认构造函数

3、什么时候会重新创建fragment,when设备配置参数发生变化(如:横竖屏切换),

4、既然是调用默认构造函数,那么通过重载传递的参数将全部丢失

5、而使用系统推荐的 Fragment.setArguments(Bundle)来传递参数。就可以有效的避免这一个问题,当你的Fragment销毁的时候,其中的Bundle会保存下来,当要重新创建的时候会检查Bundle是否为null,如果不为null,就会使用bundle作为参数来重新创建fragment.

6、setArguments can only be called before the Fragment is attached to the Activity.

setArguments方法的调用必须要在Fragment与Activity关联之前,即setArgument方法的使用必须要在FragmentTransaction 的commit之前使用

public class FavAndFansActivity extends BaseActivity {
	private static final String TAG = "FavAndFansActivity";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_other_user_info);
		String uid = getIntent().getStringExtra("uid");
		boolean isSelf = getIntent().getBooleanExtra("isSelf", false);
		int type = getIntent().getIntExtra("type", 0);
		FragmentManager fm = getSupportFragmentManager();
		if (fm.findFragmentByTag(TAG) == null) {
			FragmentTransaction ft = fm.beginTransaction();
			ft.add(R.id.other_user_layout, FavoriteAndFansFragment.newInstance(uid, isSelf, type), TAG)
					.commit();
		}
	}
}

你可能感兴趣的:(android,Fragment)