Android中带@NonNull注解的createFragment方法如何正确返回Fragment消除告警
解决@NonNull注解告警的方案
方法被@NonNull修饰,要求所有分支都必须返回非空的Fragment实例,你当前返回null的逻辑不符合注解约束,才会触发告警。你可以根据业务场景选以下两种兜底方案替换最后的return null:
- 如果你确定当前适配器只会被那四个城市Activity调用,兜底直接抛出异常即可,出现异常时可以快速发现逻辑问题:
throw new IllegalArgumentException("不支持的Activity类型: " + className);
- 如果你需要兼容未知场景不崩溃,可以自己实现一个空白占位的
EmptyFragment,兜底返回这个Fragment的实例即可。
更优的Fragment返回逻辑实现
你当前的硬编码类名、多层嵌套判断的逻辑扩展性极差,新增城市需要修改大量代码,推荐以下两种优化方案:
方案1:枚举工厂统一管理
把城市对应的Fragment映射关系统一放到枚举里管理,后续新增城市只需要新增枚举项即可,不需要修改核心逻辑:
public enum CityFragmentFactory { VANCOUVER(VancouverActivity.class.getSimpleName(), new Class[]{ VancouverMainFragment.class, VancouverAttractionsFragment.class, VancouverCoffeeFragment.class, VancouverRestaurantFragment.class, VancouverActivitiesFragment.class }), SASKATOON(SaskatoonActivity.class.getSimpleName(), new Class[]{ SaskatoonMainFragment.class, SaskatoonAttractionsFragment.class, SaskatoonCoffeeFragment.class, SaskatoonRestaurantFragment.class, SaskatoonActivitiesFragment.class }), TORONTO(TorontoActivity.class.getSimpleName(), new Class[]{ TorontoMainFragment.class, TorontoAttractionsFragment.class, TorontoCoffeeFragment.class, TorontoRestaurantFragment.class, TorontoActivitiesFragment.class }), ST_JOHNS(StJohnsActivity.class.getSimpleName(), new Class[]{ StJohnsMainFragment.class, StJohnsAttractionsFragment.class, StJohnsCoffeeFragment.class, StJohnsRestaurantFragment.class, StJohnsActivitiesFragment.class }); private final String activityClassName; private final Class<? extends Fragment>[] fragmentClasses; CityFragmentFactory(String activityClassName, Class<? extends Fragment>[] fragmentClasses) { this.activityClassName = activityClassName; this.fragmentClasses = fragmentClasses; } public static Fragment create(String activityClassName, int position) { for (CityFragmentFactory factory : values()) { if (factory.activityClassName.equals(activityClassName)) { // 处理position越界 int safePos = Math.max(0, Math.min(position, factory.fragmentClasses.length - 1)); try { return factory.fragmentClasses[safePos].newInstance(); } catch (Exception e) { throw new RuntimeException("Fragment实例化失败", e); } } } throw new IllegalArgumentException("不支持的Activity:" + activityClassName); } }
优化后你的原方法可以简化为:
@NonNull @Override public Fragment createFragment(int position) { String className = mContext.getClass().getSimpleName(); return CityFragmentFactory.create(className, position); }
方案2:接口解耦(更推荐)
不要在适配器里判断宿主类型,直接让所有使用该适配器的Activity实现统一的接口,完全解耦适配器和具体Activity的绑定关系:
- 首先定义接口
public interface FragmentProvider { Fragment getFragmentByPosition(int position); }
- 四个城市Activity都实现该接口,返回对应位置的Fragment实例
- 适配器里直接调用接口方法即可
@NonNull @Override public Fragment createFragment(int position) { if (mContext instanceof FragmentProvider) { return ((FragmentProvider) mContext).getFragmentByPosition(position); } throw new IllegalArgumentException("宿主Activity必须实现FragmentProvider接口"); }
后续新增城市不需要修改适配器任何代码,只需要新Activity实现FragmentProvider接口即可。
内容的提问来源于stack exchange,提问作者DevGoran
相关产品推荐
相关产品推荐

