ArrayList越界异常:构造函数中集合有效但onCreate中长度为0的原因
问题原因与解决方案:Activity构造函数传参后ArrayList在onCreate中为空
兄弟,你遇到的这个问题其实是Android开发里一个典型的误区——Activity不能用自定义带参构造来传递数据,我来给你拆解清楚:
为什么mData在onCreate里大小变成0?
Android的Activity实例是由系统负责创建的,系统只会调用它的无参构造函数,你自己定义的ViewDetail(Context c, ArrayList<DataModel> data)这个构造根本没被执行!
你看代码里private ArrayList<DataModel> mData=new ArrayList<>();,这行在类初始化时就创建了一个空的ArrayList,而自定义构造里的this.mData = data;从来没跑过,所以onCreate里打印的就是这个空集合的大小0;而你之前构造函数里的日志,其实是你自己手动new这个Activity实例时打的,但那个实例根本不是系统用来启动的那个!
正确的解决方式:用Intent传递数据
Android组件间传递数据的标准方式是用Intent,因为你的DataModel是自定义类,需要先让它实现Parcelable(推荐,比Serializable性能好)或者Serializable接口,然后通过Intent携带数据。
步骤1:让DataModel实现Parcelable
public class DataModel implements Parcelable { // 假设你的类有这些字段,根据实际情况修改 private String title; private int id; // 普通构造函数 public DataModel(String title, int id) { this.title = title; this.id = id; } // Parcelable要求的构造,用于从Parcel读取数据 protected DataModel(Parcel in) { title = in.readString(); id = in.readInt(); } // Parcelable必备的Creator public static final Creator<DataModel> CREATOR = new Creator<DataModel>() { @Override public DataModel createFromParcel(Parcel in) { return new DataModel(in); } @Override public DataModel[] newArray(int size) { return new DataModel[size]; } }; @Override public int describeContents() { return 0; // 几乎所有情况都返回0 } @Override public void writeToParcel(Parcel dest, int flags) { // 把字段写入Parcel,顺序要和读取时一致 dest.writeString(title); dest.writeInt(id); } // 你的getter、setter方法 public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getId() { return id; } public void setId(int id) { this.id = id; } }
步骤2:启动ViewDetail时用Intent传递数据
在原来启动ViewDetail的地方(比如另一个Activity里),把数据放到Intent里:
// 假设你已经有了要传递的ArrayList<DataModel> dataList Intent intent = new Intent(this, ViewDetail.class); // 传递ArrayList,用putParcelableArrayListExtra intent.putParcelableArrayListExtra("KEY_DATA_LIST", dataList); // 同时传递position参数 intent.putExtra("position", (short) clickedPosition); startActivity(intent);
步骤3:在ViewDetail的onCreate中获取数据
删掉你的自定义构造函数,直接在onCreate里从Intent拿数据:
public class ViewDetail extends AppCompatActivity { private static final String TAG = "val"; private static final String POSITION_CLICKED = "position"; private static final String KEY_DATA_LIST = "KEY_DATA_LIST"; private ArrayList<DataModel> mData; private Context mC; // 系统会自动使用无参构造,不用手动写也可以 public ViewDetail() { super(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_detail); // 从Intent中获取传递过来的ArrayList mData = getIntent().getParcelableArrayListExtra(KEY_DATA_LIST); // 这里要注意判空,避免NullPointerException Log.v(TAG,"MDATA SIZE2 "+ (mData != null ? mData.size() : 0)); short pos = 0; try { pos = getIntent().getExtras().getShort(POSITION_CLICKED); } catch (Exception e) { e.printStackTrace(); } } }
额外提醒
- 永远不要给Activity、Service这类系统组件自定义带参构造,系统不会调用它们,只会用无参构造实例化组件。
- 如果你的DataModel比较简单,也可以用Serializable接口,步骤类似,只是传递时用
putSerializableExtra,获取时用getSerializableExtra,但Parcelable的性能更好,推荐用它。
内容的提问来源于stack exchange,提问作者amir dt
相关产品推荐
相关产品推荐

