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();
}
}
}