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