两个Fragment使用同一ArrayAdapter类的不同实例绑定ListView时仅首个显示列表可加载数据的问题咨询
你完全不需要为每个Fragment单独编写Adapter和Model类,复用同一个类的不同实例是完全可行的,你的问题出在代码里的几个细节处理上,我帮你梳理一下:
问题1:Adapter绑定ListView的时机错误
看你的getPartAdded()和getPartOutTaken()方法,你把listPartAdded.setAdapter(adapter);放在了Volley请求发送之后,但Volley是异步请求,这行代码会在请求还没返回数据时就执行,此时Adapter的数据集还是空的。虽然你在响应回调里调用了notifyDataSetChanged(),但如果Fragment还没完成视图初始化,ListView可能不会正确响应刷新。
修正方案:把设置Adapter的代码移到Fragment的onCreateView方法里,和Adapter初始化放在一起,比如:
// FragmentPartAdded 的 onCreateView 示例 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_part_added, container, false); listPartAdded = view.findViewById(R.id.list_part_added); modelPartAdded = new ArrayList<>(); adapter = new AdapterPartsIntakenOut(modelPartAdded, getContext()); // 在这里绑定Adapter,一次性完成 listPartAdded.setAdapter(adapter); return view; }
问题2:数据加载的生命周期时机不对
当Activity启动时,只有当前显示的Fragment会执行完整的生命周期(比如onResume),第二个Fragment可能处于暂停状态,此时即使数据集更新了,ListView也不会触发刷新。
修正方案:把数据加载的方法(getPartAdded()/getPartOutTaken())放到Fragment的onResume方法中,这样每次Fragment切换到前台可见时,都会重新加载数据并更新视图:
@Override public void onResume() { super.onResume(); getPartAdded(); // 或者 getPartOutTaken(),对应各自Fragment }
问题3:异步回调中UI更新的严谨性
Volley的响应回调是在后台线程执行的,虽然notifyDataSetChanged()本身是线程安全的,但最好显式切换到UI线程执行更新操作,避免潜在的视图异常:
// 在Volley的onResponse回调中修改 @Override public void onResponse(JSONArray response) { for (int i = 0; i < response.length(); i++) { try { String actionType = response.getJSONObject(i).getString("action_type"); String onDate = response.getJSONObject(i).getString("on_date"); modelPartAdded.add(new ModelPartIntakenOuttake(actionType,onDate)); } catch (JSONException e) { e.printStackTrace(); } } // 切换到UI线程更新Adapter getActivity().runOnUiThread(new Runnable() { @Override public void run() { adapter.notifyDataSetChanged(); } }); }
另外,你之前写的mRunnable清空数据集的操作可以简化,直接在加载数据前调用modelPartAdded.clear()即可,不需要额外通过runOnUiThread执行,因为getPartAdded()本身是在UI线程调用的(onResume是UI线程方法)。
总结
复用同一个Adapter和Model类完全没问题,这也是推荐的做法,能减少代码冗余。你只需要调整视图绑定、数据加载的时机,以及确保UI更新在正确的线程执行,两个Fragment的列表就能正常加载数据了。
备注:内容来源于stack exchange,提问作者Gabriel Rogath

