Android新手求助:Volley解析后ArrayList始终为空
问题分析与解决方案
嘿,刚接触Android和Stack Overflow完全没问题,咱们一步步来搞定你的问题~
你的核心问题在于Volley的网络请求是异步执行的:当你调用getList()的时候,代码会立刻把空的parseItemList返回给HomeFragment,而Volley的onResponse()方法要等网络请求完成后才会执行(这时候才会填充列表)。所以你拿到的永远是初始的空列表。
解决方案:用回调接口处理异步结果
最适合新手理解的方式是定义一个回调接口,让JsonParse在请求完成后主动把数据传递给HomeFragment,而不是同步返回。
步骤1:定义回调接口
先创建一个接口,用来传递请求成功/失败的结果:
public interface OnDataLoadedListener { void onDataLoaded(ArrayList<ParseItem> itemList); void onError(String errorMessage); }
步骤2:修改JsonParse类
把getList()改成接收回调的方法,去掉返回值,在请求完成后通过回调传递数据:
public class JsonParse { Context context; String json_url = "myurl"; public JsonParse(Context context) { this.context = context; } // 改为接收回调接口,不再直接返回列表 public void getList(final OnDataLoadedListener listener) { JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.POST, json_url, null, new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { ArrayList<ParseItem> parseItemList = new ArrayList<>(); for (int i = 0; i < response.length(); i++) { try { JSONObject jsonObject = response.getJSONObject(i); ParseItem parseItem = new ParseItem(); String naslov = jsonObject.getString("naslov"); String url = jsonObject.getString("url"); parseItem.setTitle(naslov); parseItem.setUrl(url); JSONArray niz = jsonObject.getJSONArray("niz"); ArrayList<String> podnaslovTMP = new ArrayList<>(); ArrayList<String> podurlTMP = new ArrayList<>(); for (int j = 0; j < niz.length(); j++) { JSONObject nizOBJ = niz.getJSONObject(j); String podnaslov = nizOBJ.getString("podnaslov"); String podurl = nizOBJ.getString("podurl"); podnaslovTMP.add(podnaslov); podurlTMP.add(podurl); } // 把临时子列表设置给ParseItem(记得你的ParseItem类要有对应getter/setter) parseItem.setPodnaslovList(podnaslovTMP); parseItem.setPodurlList(podurlTMP); parseItemList.add(parseItem); } catch (JSONException e) { e.printStackTrace(); listener.onError("解析JSON出错:" + e.getMessage()); } } // 请求成功,通过回调传递数据 listener.onDataLoaded(parseItemList); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); listener.onError("网络请求失败:" + error.getMessage()); } }); MySingleton.getInstance(context).addToRequestQueue(jsonArrayRequest); } }
步骤3:修改HomeFragment调用逻辑
在Fragment里调用getList()时,传入回调接口实现,在回调里获取数据并更新UI:
public class HomeFragment extends Fragment implements View.OnClickListener { private Context context; private static final int REQUEST_CALL = 1; private View view; private ArrayList<ParseItem> arrayList = new ArrayList<>(); public HomeFragment() { } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_home, container, false); init(); JsonParse jsonParse = new JsonParse(getActivity()); // 调用getList并传入回调 jsonParse.getList(new OnDataLoadedListener() { @Override public void onDataLoaded(ArrayList<ParseItem> itemList) { // 请求成功,获取到填充好的列表 arrayList = itemList; // 这里可以更新你的UI,比如设置RecyclerView适配器 // 注意:更新UI前要确保Fragment处于活跃状态,避免崩溃 if (isAdded()) { // 示例:recyclerView.setAdapter(new MyCustomAdapter(arrayList)); } } @Override public void onError(String errorMessage) { // 请求失败,提示用户 if (isAdded()) { Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_SHORT).show(); } } }); return view; } // 你的init()和onClick()方法... }
额外提醒
- 异步操作的核心就是不能同步等待结果,必须通过回调、LiveData、协程等方式处理后续逻辑
- 在回调里更新UI时,一定要检查Fragment是否还附着在Activity上(比如用
isAdded()),避免内存泄漏或空指针异常 - 如果以后想更优雅地处理异步,可以学习Jetpack的
LiveData或者Kotlin协程,不过先把回调的逻辑搞懂是基础~
内容的提问来源于stack exchange,提问作者ShoneBl
相关产品推荐
相关产品推荐

