Volley取数后用Bundle传值到Fragment触发空指针异常,如何解决?
解决Fragment间Bundle传值的空指针问题
嘿,我看你遇到了Attempt to invoke virtual method 'java.lang.String android.os.BaseBundle.getString(...)' on a null object reference这个错误,本质就是你在ChooseTab这个Fragment里调用getArguments()时拿到了null,导致调用getString()触发了空指针。我来帮你拆解问题并给出修复方案:
为什么会出现这个错误?
主要有两个核心原因:
- 你可能在某些场景下创建
ChooseTab实例时,没有给它设置Arguments(比如直接new ChooseTab()但忘了调用setArguments()); - 最关键的是,Volley的网络请求是异步的,你可能在
count还没从接口拿到值的时候,就急着执行Fragment跳转传值的逻辑了,甚至可能因为时机不对导致Bundle根本没传递成功。
具体的修复步骤
1. 修正异步请求的传值时机
你的getCount()方法是异步请求,count的值要等接口返回后才会被赋值。现在你是在点击事件里直接跳转传值,这时候count可能还没拿到,甚至会因为请求延迟导致Bundle传递逻辑出问题。我们把跳转逻辑移到Volley的onResponse回调里,确保拿到count后再传值:
修改getCount()方法,把跳转逻辑放在请求成功后:
private void getCount() { String url="http://192.168.1.106:9500/api/restqueue/"; String json_req = "json_req"; JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { JSONObject object=new JSONObject(response.toString()); count=object.getString("name"); // 接口请求成功,拿到count后再跳转传值 navigateToChooseTab(); } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // 这里可以加个错误提示,比如Toast告诉用户请求失败了 Toast.makeText(getActivity(), "请求失败,请重试", Toast.LENGTH_SHORT).show(); } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { Map<String, String> headers = new HashMap<>(); String credentials = name+":"+pass; String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); headers.put("Content-type", "application/json"); headers.put("Authorization", auth); return headers; } }; AppController.getInstance().addToRequestQueue(req, json_req); } // 单独封装跳转逻辑,代码更清晰 private void navigateToChooseTab() { fm = getFragmentManager(); String tag = ""; tx = fm.beginTransaction(); Bundle bundle = new Bundle(); bundle.putString("totcount", count); ChooseTab choose = new ChooseTab(); choose.setArguments(bundle); tx.replace(R.id.frame, choose, tag); tx.addToBackStack(tag); tx.commit(); }
然后修改点击事件,只触发网络请求:
name.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 点击后先发起网络请求,等拿到数据再跳转 getCount(); } });
2. 在ChooseTab里加个空值判断
为了防止极端情况(比如请求失败后跳转,或者其他地方创建ChooseTab没传Bundle),在获取Bundle时先判断是否为null:
Bundle bundle = this.getArguments(); if (bundle != null) { count = bundle.getString("totcount", "empty"); } else { // 处理没有传值的情况,比如给个默认值或者提示用户 count = "empty"; Toast.makeText(getActivity(), "未获取到数据", Toast.LENGTH_SHORT).show(); }
3. 检查所有创建ChooseTab的地方
确保你所有创建ChooseTab实例的代码,都调用了setArguments()传递Bundle,不要有直接new ChooseTab()就添加到事务的情况,否则肯定会出现空指针。
额外小建议
- 不要在Fragment的
onCreateView()以外的生命周期方法里随便用getArguments(),除非你确定它已经被正确设置; - 系统会自动保存和恢复Fragment的
arguments,所以只要你是通过setArguments()设置的,Fragment重建后也能拿到值,不用额外处理。
内容的提问来源于stack exchange,提问作者Satyam Gondhale
相关产品推荐
相关产品推荐

