向Adapter传对象遇NullPointerException及跨Fragment传参问题
看起来你遇到的核心问题是Fragment生命周期时机错误导致的空指针——你直接在new Forecast_Day_Fragment()后调用addItemsRecyclerForecast(),但此时Fragment还没执行onCreateView(),RecyclerView、Adapter这些控件/对象都还没初始化,自然会抛出NullPointerException。
下面是一步步的解决方案:
1. 让自定义对象支持跨Fragment传递
首先,你的DarkSkyWeather类需要实现Parcelable(推荐,比Serializable性能更高),这样才能通过Fragment的arguments传递:
public class DarkSkyWeather implements Parcelable { // 你的类成员变量,比如示例字段: private String weatherSummary; private long timestamp; private double temperature; // 保留你的fromJson方法、构造函数等原有代码 // --- Parcelable 实现代码 --- protected DarkSkyWeather(Parcel in) { weatherSummary = in.readString(); timestamp = in.readLong(); temperature = in.readDouble(); } public static final Creator<DarkSkyWeather> CREATOR = new Creator<DarkSkyWeather>() { @Override public DarkSkyWeather createFromParcel(Parcel in) { return new DarkSkyWeather(in); } @Override public DarkSkyWeather[] newArray(int size) { return new DarkSkyWeather[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(weatherSummary); dest.writeLong(timestamp); dest.writeDouble(temperature); } }
2. 修改Fragment A的传递逻辑
不要直接调用Fragment的方法传递数据,而是通过Bundle+setArguments()传递,这是Fragment间传递数据的标准方式:
// 1. 创建你的自定义对象 DarkSkyWeather fore = DarkSkyWeather.fromJson(response, i, timestamp, i); // 2. 初始化Fragment B并传递数据 Forecast_Day_Fragment fdf = new Forecast_Day_Fragment(); Bundle args = new Bundle(); // 用自定义key存入对象,后续Fragment B要使用同一个key取出 args.putParcelable("FORECAST_ITEM", fore); fdf.setArguments(args); // 3. 执行Fragment事务(替换/添加到容器中) getSupportFragmentManager().beginTransaction() .replace(R.id.your_fragment_container_id, fdf) .addToBackStack(null) // 可选,添加到返回栈 .commit();
3. 修改Fragment B的接收与初始化逻辑
在Fragment的生命周期方法(比如onCreateView())中,先初始化RecyclerView和Adapter,再取出传递过来的数据:
public class Forecast_Day_Fragment extends Fragment { private RecyclerView mForecastRecyclerView; private ForecastAdapter mForecastAdapter; private List<DarkSkyWeather> mForecastDataList; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.your_fragment_layout, container, false); // 1. 初始化RecyclerView和数据集合 mForecastRecyclerView = rootView.findViewById(R.id.recycler_view_forecast); mForecastRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); mForecastDataList = new ArrayList<>(); mForecastAdapter = new ForecastAdapter(mForecastDataList); mForecastRecyclerView.setAdapter(mForecastAdapter); // 2. 取出传递过来的对象并更新RecyclerView if (getArguments() != null) { DarkSkyWeather receivedForecast = getArguments().getParcelable("FORECAST_ITEM"); if (receivedForecast != null) { mForecastDataList.add(receivedForecast); // 通知Adapter数据更新,用notifyItemInserted比notifyDataSetChanged更高效 mForecastAdapter.notifyItemInserted(mForecastDataList.size() - 1); } } return rootView; } // 如果后续还需要动态添加数据,可以保留这个方法,但要加空判断避免异常 public void addItemsRecyclerForecast(DarkSkyWeather fore) { if (mForecastDataList != null && mForecastAdapter != null) { mForecastDataList.add(fore); mForecastAdapter.notifyItemInserted(mForecastDataList.size() - 1); } } }
为什么原来的代码会报错?
当你new Forecast_Day_Fragment()后,Fragment还处于未附着到Activity的状态,onCreateView()还没执行,mForecastRecyclerView、mForecastAdapter这些变量都是null,此时调用addItemsRecyclerForecast()操作它们,必然会抛出NullPointerException。
而通过arguments传递数据,数据会和Fragment绑定,在onCreateView()中取出时,RecyclerView等控件已经完成初始化,就能安全操作了。
内容的提问来源于stack exchange,提问作者qkjedklajsdfkljsadfklöjsdaklöf

