Понимание Android Parcelable - разделение не работает

Итак, я решил попробовать Parcelling в Android сегодня, быстро смоделировал это:

public class Unit implements Parcelable {
    private String unitName;
    private int view;
    private Double value;

    /**
     * Constructor
     */
    public Unit() { }

    /**
     * Constructor
     * @param unitName
     */
    public Unit(String unitName) {
        this.unitName = unitName;
    }

    /**
     * Constructor
     * @param unitName
     * @param view
     */
    public Unit(String unitName, int view, Double value) {
        this.unitName = unitName;
        this.view = view;
        this.value = value;
    }

    /**
     * Set the name of the unit of measurement
     * @param name
     */
    public void setUnitName(String name) {
        this.unitName = name;
    }

    /**
     * Set whether the unit of measurement is viewable
     * @param view
     */
    public void setView(int view) {
        this.view = view;
    }

    /**
     * Set the value of the unit
     * @param value
     */
    public void setValue(Double value) { this.value = value; }

    /**
     * Return the unit name
     * @return unitName
     */
    public String getUnitName() {
        return unitName;
    }

    /**
     * Return whether the unit is viewable
     * @return view
     */
    public int getView() {
        return view;
    }

    /**
     * Return the value of this unit
     * @return value
     */
    public Double getValue() { return value; }

    /**
     * Methods for parcelling here
     */

    /**
     * Constructor for parcelling
     * @param in
     */
    public Unit(Parcel in) {
        //
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(new ArrayList<Unit>() {
            //huh?
        });
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Unit createFromParcel(Parcel in) {
            return new Unit(in);
        }

        public Unit[] newArray(int size) {
            return new Unit[size];
        }
    };
}

Как вы, вероятно, заметили, моя реализация методов, которые я переопределяю из интерфейса Parcelable, неполна. Но продолжая, этот класс — всего лишь объект, который должен быть разделен с другим классом.

Теперь вот моя основная деятельность:

public class MyActivity extends Activity {
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button send = (Button) findViewById(R.id.sendParcel);
        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ArrayList<Unit> units = getUnits();
                Intent i = new Intent(getApplicationContext(), UnitListActivity.class);
                i.putParcelableArrayListExtra("units", units);
                startActivity(i);
            }
        });
    }

    /**
     * Return an arraylist of units
     * @return units
     */
    public ArrayList<Unit> getUnits() {
        ArrayList<Unit> units = new ArrayList<Unit>();
        units.add(new Unit("acceleration", 1, 56.45));
        units.add(new Unit("kilograms", 0, 5830.54345));
        units.add(new Unit("metres", 1, 543.54));
        units.add(new Unit("kilometres", 1, 32.43));
        units.add(new Unit("grams", 1, 453.654));
        units.add(new Unit("kilograms", 0, 8.5));
        units.add(new Unit("litres", 1, 344.3));
        units.add(new Unit("millilitres", 0, 4543.879));
        units.add(new Unit("decimeter", 1, 5084903.564567));
        return units;
    }
}

По сути, есть кнопка, которая при нажатии создаст Intent и попытается разделить ArrayList с объектом, который реализует интерфейс Parcelable. Класс, которому он пытается передать это ListActivity, код которого находится здесь:

public class UnitListActivity extends ListActivity {

    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        UnitListAdapter mTypeAdapter = new UnitListAdapter(getApplicationContext(), bundle.getParcelableArrayList("units"));
        setListAdapter(mTypeAdapter);
    }
}

Я сделал этот адаптер для ListActivity здесь:

public class UnitListAdapter extends ArrayAdapter<Unit> {

    private ArrayList<Unit> unitsList;
    private Context context;

    public UnitListAdapter(Context c, ArrayList<Unit> units) {
        super(c, R.layout.unit_values, units);
        this.context = c;
        this.unitsList = units;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parentView) {
        View view = null;
        LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflator.inflate(R.layout.unit_values, null);
        TextView textView = (TextView) view.findViewById(R.id.unit_name);
        CheckBox checkBox = (CheckBox) view.findViewById(R.id.check);

        //check box set on check changed listener if I get this far for later

        if(unitsList.get(position).getView() == 1) {
            textView.setText(unitsList.get(position).getUnitName());
            checkBox.setChecked(true);
        } else {
            textView.setText(unitsList.get(position).getUnitName());
        }

        return view;
    }

}

Теперь я не понимаю, почему в ListActivity этой строке: UnitListAdapter mTypeAdapter = new UnitListAdapter(getApplicationContext(), bundle.getParcelableArrayList("units")); жалуется, что вместо получения объектов Unit он получает объекты Parcelable, поскольку класс Unit их реализует.

Означает ли это, что в моем адаптере я должен изменить список, чтобы ожидать объекты Parcelable, и если это означает, что он изменит то, как я их читаю??

Я также не понимаю writeToParcel, в документации сказано, что он будет сглаживать объект, поэтому я подумал, что, поскольку я хочу сгладить список, мне понадобится метод writeList, но что после этого? кажется, что он сглаживает объект Unit, а не список.

Это также заставляет меня спросить о конструкторе:

public Unit(Parcel in) {
        //
}

Я предполагаю, что мне нужно сделать что-то вроде этого:

readTypedList() - Я не понимаю, зачем мне это делать, ведь я буду создавать посылки. Поэтому я не уверен, как реализовать эту вещь... Мне бы очень хотелось понять, как работает парцеллирование, я не нашел документацию, которая была бы полезной, и как в этом примере это будет работать успешно. Помощь и совет очень ценятся.


person user2405469    schedule 27.07.2014    source источник


Ответы (2)


Я думаю, вам нужно явно указать Parcelable Creator, какой тип ему нужно создать, поэтому попробуйте изменить свой код на это:

public static final Parcelable.Creator<Unit> CREATOR = new Parcelable.Creator<Unit>() {
    public Unit createFromParcel(Parcel in) {
        return new Unit(in);
    }

    public Unit[] newArray(int size) {
        return new Unit[size];
    }
};
person John J Smith    schedule 27.07.2014
comment
Извините, но это не работает, UnitListAdapter mTypeAdapter = new UnitListAdapter(getApplicationContext(), bundle.getParcelableArrayList(units)); продолжает просить меня преобразовать bundle.getParcelableArrayList в ArrayList‹Parcelable›, но мой класс Unit реализует его, поэтому я не знаю, почему он жалуется, не может расширить интерфейс, поэтому... - person user2405469; 04.08.2014

person    schedule
comment
Не могли бы вы предоставить больше информации о вашем ответе? Обычно хорошей практикой является небольшое объяснение ответов, которые вы публикуете. - person Bono; 07.03.2015