Activity和Fragment通信遇到的坑——为什么要用setArguments方法?

在很早的版本Studio中是可以写如下的代码的

 public ParamFragment() {
    }

  public ParamFragment(int type) {
    }

也就意味着你可以通过构造方法传递参数进来,后来studio禁止了这种写法

在这里插入图片描述
在Android studio 3.4版本的提示中你可以看到官方推荐你用setArguments来传递参数
因为我之前没有看过setArguments的介绍,认为这个东西没有啥了不起的,还是我行我素用下面的方法通信

public ParamFragment setType(int type) {
      ....
        return this;
    }
 new ParamFragment().setType(1)

测试的时候也没有发现什么问题,还沾沾自喜觉得这种办法很简单很方便

然后麻烦就出现了

线上日志提示app崩溃,代码定位到存在空指针异常,是参数为空导致的。
可是Fragment创建的时候是传递参数进去的,不可能参数为空的,那么到底是哪里出问题了呢?
于是我开始测试一下Activty和Fragment通信

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("tag", "onCreate: 1");
        Fragment fragment = new ParamFragment();
        Log.i("tag", "onCreate: 2");
        getSupportFragmentManager().beginTransaction().add(R.id.ll_container, fragment).commit();
    }
}
public class ParamFragment extends Fragment {


    int type = 0;
    public ParamFragment() {
        Log.i("tag", "Test: fargment constructor");
    }

    public ParamFragment setType(int type) {
        this.type = type;
        Log.i("tag", "Test: fargment setType");
        return this;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.i("tag", "Test: type is "+type);
        TextView textView = new TextView(getActivity());
        textView.setText("haha");
        return textView;
    }

}

运行结果如下

2019-04-28 22:19:32.437 10999-10999/com.justtest I/tag: onCreate: 1
2019-04-28 22:19:32.439 10999-10999/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:19:32.439 10999-10999/com.justtest I/tag: onCreate: 2
2019-04-28 22:19:32.446 10999-10999/com.justtest I/tag: Test: type is 0

这个和预期结果一样,参数为0

修改Activity里面的代码:

  Log.i("tag", "onCreate: 1");
 Fragment fragment = new ParamFragment().setType(1);
  Log.i("tag", "onCreate: 2");

结果如下所示:

2019-04-28 22:21:49.026 11243-11243/com.justtest I/tag: onCreate: 1
2019-04-28 22:21:49.044 11243-11243/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:21:49.044 11243-11243/com.justtest I/tag: Test: fargment setType
2019-04-28 22:21:49.044 11243-11243/com.justtest I/tag: onCreate: 2
2019-04-28 22:21:49.075 11243-11243/com.justtest I/tag: Test: type is 1

好像也没啥特殊的地方哈,这个时候我们旋转屏幕看看会发生什么

2019-04-28 22:21:49.026 11243-11243/com.justtest I/tag: onCreate: 1
2019-04-28 22:21:49.044 11243-11243/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:21:49.044 11243-11243/com.justtest I/tag: Test: fargment setType
2019-04-28 22:21:49.044 11243-11243/com.justtest I/tag: onCreate: 2
2019-04-28 22:21:49.075 11243-11243/com.justtest I/tag: Test: type is 1
2019-04-28 22:23:06.242 11243-11243/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:23:06.270 11243-11243/com.justtest I/tag: onCreate: 1
2019-04-28 22:23:06.270 11243-11243/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:23:06.270 11243-11243/com.justtest I/tag: Test: fargment setType
2019-04-28 22:23:06.270 11243-11243/com.justtest I/tag: onCreate: 2
2019-04-28 22:23:06.274 11243-11243/com.justtest I/tag: Test: type is 0
2019-04-28 22:23:06.276 11243-11243/com.justtest I/tag: Test: type is 1

屏幕旋转会发生呢?Activity的销毁和重建,与此对应的Fragment也是经历了销毁和重建的过程

2019-04-28 22:23:06.242 11243-11243/com.justtest I/tag: Test: fargment constructor

在其执行前没有执行onCreate: 1,之后也没有执行fargment setType,说明这是我们的系统认为帮我们恢复了
fragment,系统做了一件好事——自认为好心的帮我们重建了这个fragment,但是我们可以看到

2019-04-28 22:23:06.274 11243-11243/com.justtest I/tag: Test: type is 0
2019-04-28 22:23:06.276 11243-11243/com.justtest I/tag: Test: type is 1

这里初始化调用了onCreateView两次,一次是我们自己创建的碎片调用的,一次是系统帮我们恢复的碎片调用,这个时候我们就能看到同一个碎片但是值却不一样了,type 一个是1一个是0,系统帮我们恢复的碎片里面的值却没有保存上

看到这里你也就明白了为什么线上会报空指针异常了

系统帮我们恢复的碎片并没有将数据保存下来,导致读取数据的时候造成的空指针异常

接下来我们用setArguments方法试试

public class ParamFragment extends Fragment {


    int type = 0;
    public ParamFragment() {
        Log.i("tag", "Test: fargment constructor");
    }

    public ParamFragment  setType(int type) {
        this.type = type;
        Log.i("tag", "Test: fargment setType");
        return this;
    }

    public static ParamFragment  newInstance(int type) {
        ParamFragment fragment = new ParamFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("type",type);
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        getArgumentsData();
        Log.i("tag", "Test: type is "+type);
        TextView textView = new TextView(getActivity());
        textView.setText("haha");
        return textView;
    }

    private void getArgumentsData() {
        Bundle bundle = getArguments();
        if(bundle!=null){
            type = bundle.getInt("type");
        }
    }

}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("tag", "onCreate: 1");
        Fragment fragment = ParamFragment.newInstance(1);
        Log.i("tag", "onCreate: 2");
        getSupportFragmentManager().beginTransaction().add(R.id.ll_container, fragment).commit();
    }
}

这个时候先正常启动再旋转屏幕一下

2019-04-28 22:35:13.036 11882-11882/com.justtest I/tag: onCreate: 1
2019-04-28 22:35:13.042 11882-11882/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:35:13.042 11882-11882/com.justtest I/tag: onCreate: 2
2019-04-28 22:35:13.048 11882-11882/com.justtest I/tag: Test: type is 1
2019-04-28 22:36:06.323 11882-11882/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:36:06.353 11882-11882/com.justtest I/tag: onCreate: 1
2019-04-28 22:36:06.353 11882-11882/com.justtest I/tag: Test: fargment constructor
2019-04-28 22:36:06.353 11882-11882/com.justtest I/tag: onCreate: 2
2019-04-28 22:36:06.365 11882-11882/com.justtest I/tag: Test: type is 1
2019-04-28 22:36:06.367 11882-11882/com.justtest I/tag: Test: type is 1

果然结果是——系统把数据正常保存下来了

具体想知道setArguments做了什么操作,请看下面这篇博客
Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数

平时不注意的细节只有被崩溃教做人,希望大家吸取这次教训,以后注意这个坑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值