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

求带泛型List字段的DialogCar类的Builder模式实现方案

Got it, let's work through this together. You need a Builder pattern for your generic DialogCar<T> class that implements Parcelable, with proper handling for the List<T> field. Here's a complete, robust implementation that covers both the Parcelable requirements and the generic Builder logic.

Complete Implementation

import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;

public class DialogCar<T extends Parcelable> implements Parcelable {
    private final String type;
    private final List<T> selectedValues;

    // Private constructor, only accessible via Builder
    private DialogCar(Builder<T> builder) {
        this.type = builder.type;
        // Make a copy of the list to prevent external modifications to internal state
        this.selectedValues = new ArrayList<>(builder.selectedValues);
    }

    // Parcelable deserialization constructor
    protected DialogCar(Parcel in) {
        type = in.readString();
        // Read generic list using the class loader to handle type T
        selectedValues = in.readArrayList(getClass().getClassLoader());
    }

    public static final Creator<DialogCar> CREATOR = new Creator<DialogCar>() {
        @Override
        public DialogCar createFromParcel(Parcel in) {
            return new DialogCar(in);
        }

        @Override
        public DialogCar[] newArray(int size) {
            return new DialogCar[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(type);
        dest.writeList(selectedValues);
    }

    // Getters with state protection
    public String getType() {
        return type;
    }

    public List<T> getSelectedValues() {
        // Return a copy to prevent external code from modifying the internal list
        return new ArrayList<>(selectedValues);
    }

    // Generic Builder inner class
    public static class Builder<T extends Parcelable> {
        private String type;
        private List<T> selectedValues = new ArrayList<>();

        public Builder<T> type(String type) {
            this.type = type;
            return this;
        }

        // Set the entire list of selected values
        public Builder<T> selectedValues(List<T> selectedValues) {
            if (selectedValues != null) {
                this.selectedValues.clear();
                this.selectedValues.addAll(selectedValues);
            }
            return this;
        }

        // Convenience method to add a single selected value
        public Builder<T> addSelectedValue(T value) {
            if (value != null) {
                this.selectedValues.add(value);
            }
            return this;
        }

        public DialogCar<T> build() {
            // Optional validation to ensure required fields are set
            if (type == null || type.trim().isEmpty()) {
                throw new IllegalArgumentException("Type cannot be null or empty");
            }
            return new DialogCar<>(this);
        }
    }
}

Key Details Explained

  • Generic Constraint: T extends Parcelable is required because we're serializing/deserializing List<T> via Parcel. If your T doesn't need to be Parcelable, you can remove this constraint—but note that the Parcelable implementation will break unless you also remove the Parcelable logic entirely.
  • State Immutability: We copy the list in both the DialogCar constructor and the getSelectedValues() method. This prevents external code from modifying the internal state of the DialogCar instance after it's built.
  • Flexible List Handling: The Builder includes both selectedValues() (to set the entire list) and addSelectedValue() (to add individual items) for convenience.
  • Validation: The build() method includes a basic check for a non-empty type field—you can extend this to add more validation rules as needed (e.g., ensuring selectedValues isn't empty if required).

Usage Example

First, let's define a sample Parcelable class to use as our generic type T:

import android.os.Parcel;
import android.os.Parcelable;

public class CarOption implements Parcelable {
    private String label;

    public CarOption(String label) {
        this.label = label;
    }

    protected CarOption(Parcel in) {
        label = in.readString();
    }

    public static final Creator<CarOption> CREATOR = new Creator<CarOption>() {
        @Override
        public CarOption createFromParcel(Parcel in) {
            return new CarOption(in);
        }

        @Override
        public CarOption[] newArray(int size) {
            return new CarOption[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(label);
    }
}

Now you can use the Builder to create DialogCar instances in two ways:

// 1. Build with a pre-existing list
List<CarOption> options = new ArrayList<>();
options.add(new CarOption("Electric"));
options.add(new CarOption("Hybrid"));

DialogCar<CarOption> dialogCar1 = new DialogCar.Builder<CarOption>()
        .type("car_power_type")
        .selectedValues(options)
        .build();

// 2. Build by adding individual items one by one
DialogCar<CarOption> dialogCar2 = new DialogCar.Builder<CarOption>()
        .type("car_body_style")
        .addSelectedValue(new CarOption("SUV"))
        .addSelectedValue(new CarOption("Sedan"))
        .addSelectedValue(new CarOption("Truck"))
        .build();

内容的提问来源于stack exchange,提问作者ghufranne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:57:28