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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:47:25