Fragment结合Volley库时无法调用findViewById()的解决方案
问题根因
编译报错的核心原因有两点:
Fragment自身没有直接提供findViewById()方法,你在Volley的onResponse回调里直接调用该方法,找不到匹配的方法签名,直接触发编译错误。- 你在
onCreateView中写的ProgressBar progressBar = rootView.findViewById(R.id.rolling)是方法局部变量,作用域仅限onCreateView内部,loadResultsList方法和内部的网络回调根本访问不到这个实例。
初始化位置问题解答
ProgressBar的初始化确实需要放在布局加载完成的生命周期节点(onCreateView或者onViewCreated都可以),通过加载得到的根View调用findViewById,但不能把它定义成方法局部变量,要和你已经写的ListView一样,提为Fragment类的成员变量,才能在全类范围内访问。
正确实现方案
- 首先在类的成员变量位置声明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 } // ... 其余原有代码 }
- 在
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; }
- 删除
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); } }
- 在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
相关产品推荐
相关产品推荐

