You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fragment结合Volley库时无法调用findViewById()的解决方案

问题根因

编译报错的核心原因有两点:

  • Fragment 自身没有直接提供findViewById()方法,你在Volley的onResponse回调里直接调用该方法,找不到匹配的方法签名,直接触发编译错误。
  • 你在onCreateView中写的ProgressBar progressBar = rootView.findViewById(R.id.rolling)是方法局部变量,作用域仅限onCreateView内部,loadResultsList方法和内部的网络回调根本访问不到这个实例。
初始化位置问题解答

ProgressBar的初始化确实需要放在布局加载完成的生命周期节点(onCreateView或者onViewCreated都可以),通过加载得到的根View调用findViewById,但不能把它定义成方法局部变量,要和你已经写的ListView一样,提为Fragment类的成员变量,才能在全类范围内访问。

正确实现方案
  1. 首先在类的成员变量位置声明ProgressBar,和ListView同级:
public class SecondFragment extends Fragment {
    private static final String BASE_URL = "Some Base URL";
    private final String EndPoint = "Some EndPoint"; // 注意你原来这里拼写错成Somr了,记得修正
    List<Result> resultsLists;
    ListView listView;
    // 新增ProgressBar成员变量
    ProgressBar progressBar;

    public SecondFragment() {
        // Required empty public constructor
    }
    // ... 其余原有代码
}
  1. 在onCreateView中初始化ProgressBar,在发起网络请求前设置进度条为可见状态:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_second, container, false);
    resultsLists = new ArrayList<>();
    listView = rootView.findViewById(R.id.listView);
    // 给成员变量progressBar赋值,不要在前面加ProgressBar类型声明,否则会变成局部变量
    progressBar = rootView.findViewById(R.id.rolling);
    // 发起请求前显示进度条
    progressBar.setVisibility(View.VISIBLE);
    
    loadResultsList();
    
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String idToDetail = String.valueOf(resultsLists.get(position).getId());
            Intent detailIntent = new Intent(getActivity(),DetailActivity.class);
            detailIntent.putExtra("idMoveIntent", idToDetail);
            startActivity(detailIntent);
        }
    });

    return rootView;
}
  1. 删除onResponse回调里错误的ProgressBar progressBar = findViewById(R.id.rolling);代码,在数据加载完成、列表绑定适配器后隐藏进度条,解析异常时也要隐藏:
@Override
public void onResponse(String response) {
    Log.d("Json Response", response);
    try {
        JSONObject obj = new JSONObject(response);
        JSONArray heroArray = obj.getJSONArray("results");
        for (int i = 0; i < heroArray.length(); i++) {
            JSONObject heroObject = heroArray.getJSONObject(i);
            Result superHero = new Result(heroObject.getString("name"), heroObject.getInt("id"), heroObject.getJSONObject("device_role").getString("name"), heroObject.getJSONObject("status").getString("value"), heroObject.getJSONObject("device_type").getJSONObject("manufacturer").getString("slug"));
            resultsLists.add(superHero);
        }
        ListViewAdapter adapter = new ListViewAdapter(resultsLists, getActivity().getApplicationContext());
        listView.setAdapter(adapter);
        // 加载成功隐藏进度条
        progressBar.setVisibility(View.GONE);
    } catch (JSONException e) {
        e.printStackTrace();
        // 解析失败也要隐藏进度条
        progressBar.setVisibility(View.GONE);
    }
}
  1. 在Volley的错误回调onErrorResponse中补充进度条隐藏逻辑,避免请求失败时进度条一直停留在页面上:
@Override
public void onErrorResponse(VolleyError error) {
    // 请求失败隐藏进度条,可按需加失败提示
    progressBar.setVisibility(View.GONE);
    Toast.makeText(getContext(), "数据加载失败,请检查网络连接", Toast.LENGTH_SHORT).show();
}

额外优化提示:Volley的网络请求是异步执行的,回调触发时Fragment可能已经被销毁,操作控件前可以先判断isAdded()返回值是否为true,避免空指针或依赖Activity的方法报错。另外不要每次调用loadResultsList都新建RequestQueue,全局复用同一个实例性能更好。

内容的提问来源于stack exchange,提问作者zazazaxky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:57:23