【问题标题】:Is there a way to make a custom object parcelable when it is constructed using another object?当使用另一个对象构造自定义对象时,有没有办法使自定义对象可打包?
【发布时间】:2019-03-30 01:52:56
【问题描述】:

我正在编写一个与汽车分类 API 交互的应用程序。我想要两个窗口:一个是用户输入他们想要的汽车类型的窗口,另一个是显示结果的窗口。

我的 API 返回一个大型 JSON 文件,每辆车大约有 40 个参数,其中只有大约 20 个对我感兴趣。我有一个自定义类来存储 API 返回的一些数据。在这个类的构造函数(称为 CarListing)中,我传递一个 JSONObject 并在构造函数内部进行 JSON 解析。

然后在线程 HttpGet 活动中调用此类,该活动本身由 MainActivity 调用。因此,对于给定的搜索,我希望从 API 中获得多个结果。我能够成功地将自定义对象返回到 MainActivity,但是在将这些数据从 MainActivity 发送到 SecondActivity 时遇到问题。最后,我想将 HashMap 传递给适配器,以便在我制作的自定义布局中使用它。

我在 Internet 上看到的大多数响应都涉及使用 Parcelable,但我不认为 JSONObject(也不是 HashMap)是 Parcelable 对象。我尝试在 CarListing 类中实现这一点,但 Android Studio 不喜欢我将 JSONObject 作为构造函数对象传递。

那么,让我的自定义对象 Parcelable 的最佳方法是什么?我应该在构造函数之外(即在我的 HttpGet 线程中)进行 JSON 解析,然后将所有 20-25 个值作为参数传递吗?我认为我最大的问题是构造函数,但我可能不正确。感谢您的帮助,如有需要,我可以提供更多信息。

这是我的自定义对象 CarListing 的代码:

package com.example.carsearchapp;

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.Serializable;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;

public class CarListing
{
    /* vehicle parameters */
    String make, model, trim, vin, color, condition, transmission, engine, drivetype, seller_type, seller_name, website, city, state;
    int year, price, mileage, cylinders;
    double distance;
    ArrayList<String> images;

    /* carfax parameters */
    boolean one_owner, clean_title;

    /* local variables that may be important */
    int index;
    JSONObject img_json, build, dealer;
    JSONArray img_array;

    public HashMap<String, String> listview_hashmap;

    /* Most strings are default N/A. Most integers are default 1, or 1970 for the case of years. */
    public CarListing(JSONObject input, int index)
    {
        try
        {
            this.images = new ArrayList<>();
            this.index = index;
            this.listview_hashmap = new HashMap<>();

            if(input.has("vin")) this.vin = input.getString("vin");
            else this.vin = "N/A";

            if(input.has("price")) this.price = input.getInt("price");
            else this.price = 1;

            if(input.has("mileage")) this.mileage = input.getInt("mileage");
            else this.mileage = 1;

            if(input.has("vdp_url")) this.website = input.getString("vdp_url");
            else this.website = "N/A";

            if(input.has("carfax_1_owner")) this.one_owner = input.getBoolean("carfax_1_owner");
            else this.one_owner = true;

            if(input.has("carfax_clean_title")) this.clean_title = input.getBoolean("carfax_clean_title");
            else this.clean_title = true;

            if(input.has("exterior_color")) this.color = input.getString("exterior_color");
            else this.color = "N/A";

            if(input.has("seller_type")) this.seller_type = input.getString("seller_type");
            else this.seller_type = "N/A";

            if(input.has("inventory_type")) this.condition = input.getString("inventory_type");
            else this.condition = "N/A";

            if(input.has("build"))
            {
                this.build = input.getJSONObject("build");

                if(this.build.has("year")) this.year = this.build.getInt("year");
                else this.year = 1970;

                if(this.build.has("make")) this.make = this.build.getString("make");
                else this.make = "N/A";

                if(this.build.has("model")) this.model = this.build.getString("model");
                else this.model = "N/A";

                if(this.build.has("trim")) this.trim = this.build.getString("trim");
                else this.trim = "N/A";

                if(this.build.has("transmission")) this.transmission = this.build.getString("transmission");
                else this.transmission = "N/A";

                if(this.build.has("drivetrain")) this.drivetype = this.build.getString("drivetrain");
                else this.drivetype = "N/A";

                if(this.build.has("cylinders")) this.cylinders = this.build.getInt("cylinders");
                else this.cylinders = 4;

                if(this.build.has("engine")) this.engine = this.build.getString("engine");
                else this.engine = "N/A";

                if(this.build.has("dist")) this.distance = this.build.getDouble("dist");
                else this.distance = 0;
            }

            if(input.has("dealer"))
            {
                this.dealer = input.getJSONObject("dealer");
                if(this.dealer.has("name")) this.seller_name = capitalizeLetters(this.dealer.getString("name"));
                else this.seller_name = "N/A";

                if(this.dealer.has("city")) this.city = this.dealer.getString("city");
                else this.city = "N/A";

                if(this.dealer.has("state")) this.state = this.dealer.getString("state");
                else this.state = "N/A";
            }

            if(input.has("media"))
            {
                this.img_json = input.getJSONObject("media");
                if(this.img_json.has("photo_links")) this.img_array = this.img_json.getJSONArray("photo_links");
                else this.img_json = null;

                int n = this.img_array.length();
                for(int i=0;i<n;i++)
                {
                    if(i >= 50) break;
                    else
                    {
                        this.images.add(img_array.getString(i));
                    }
                }
            }
        }
        catch(JSONException ex)
        {
            System.out.println("JSON Exception thrown");
        }
    }

    public String capitalizeLetters(String input)
    {
        String[] array = input.split(" ");
        String output = "";
        int n = array.length;
        for(int i=0;i<n;i++)
        {
            String cap = array[i].substring(0, 1).toUpperCase() + array[i].substring(1);
            output += cap;
        }
        return output;
    }

    public void makeHashMap()
    {
        String vehicle_title = Integer.toString(this.year) + this.make + this.model + this.trim;
        String vehicle_information = NumberFormat.getIntegerInstance().format(this.mileage) + " miles | " + this.color + " | " + this.condition + " | $" + NumberFormat.getIntegerInstance().format(this.price);
        String dealer_name = this.seller_name;
        String location = Double.toString(this.distance) + " mi. | " + this.city + ", " + this.state;
        String first_img = this.images.get(0);

        this.listview_hashmap.put("title", vehicle_title);
        this.listview_hashmap.put("information", vehicle_information);
        this.listview_hashmap.put("dealer", dealer_name);
        this.listview_hashmap.put("distance", location);
        this.listview_hashmap.put("first_image", first_img);
    }
}

【问题讨论】:

  • parcelable 实现独立于您拥有的构造函数,您应该使用 JSON 构造函数保持类原样,然后使用静态 CREATOR 和 parcel 构造函数以及 writeToParcel 进行 parcelable 实现方法是必需的实现。您应该将 JSONObject 和 JSONArray 留在 parcelable 实现之外......如果您需要保留它们,只需将它们保存为字符串,而不是由 parcel 支持。
  • 这行得通。感谢您的解释,我能够解决问题!

标签: java android class android-activity parcelable


【解决方案1】:

解决了!我必须向这个类添加四个主要参数才能使它成为 Parcelable。

第一个是接受 Parcel 对象的受保护构造函数。

第二个是一个新的静态 CREATOR 对象,具有内部方法 createFromParcel 和 newArray。

第三个是 describeContents 函数。

最后是 writeToParcel 函数。

希望其他人能够从中吸取教训,如果这可能被视为转发,我们深表歉意!

修改后的代码如下:

package com.example.marketcheckcarsearchapp;

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.Serializable;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;

public class CarListing implements Parcelable
{
    /* vehicle parameters */
    String make, model, trim, vin, color, condition, transmission, engine, drivetype, seller_type, seller_name, website, city, state;
    int year, price, mileage, cylinders;
    double distance;
    ArrayList<String> images;

    /* carfax parameters */
    boolean one_owner, clean_title;

    /* local variables that may be important */
    int index;
    JSONObject img_json, build, dealer;
    JSONArray img_array;

    public HashMap<String, String> listview_hashmap;

    /* Most strings are default N/A. Most integers are default 1, or 1970 for the case of years. */
    public CarListing(JSONObject input, int index)
    {
        try
        {
            this.images = new ArrayList<>();
            this.index = index;
            this.listview_hashmap = new HashMap<>();

            if(input.has("vin")) this.vin = input.getString("vin");
            else this.vin = "N/A";

            if(input.has("price")) this.price = input.getInt("price");
            else this.price = 1;

            if(input.has("mileage")) this.mileage = input.getInt("mileage");
            else this.mileage = 1;

            if(input.has("vdp_url")) this.website = input.getString("vdp_url");
            else this.website = "N/A";

            if(input.has("carfax_1_owner")) this.one_owner = input.getBoolean("carfax_1_owner");
            else this.one_owner = true;

            if(input.has("carfax_clean_title")) this.clean_title = input.getBoolean("carfax_clean_title");
            else this.clean_title = true;

            if(input.has("exterior_color")) this.color = input.getString("exterior_color");
            else this.color = "N/A";

            if(input.has("seller_type")) this.seller_type = input.getString("seller_type");
            else this.seller_type = "N/A";

            if(input.has("inventory_type")) this.condition = input.getString("inventory_type");
            else this.condition = "N/A";

            if(input.has("build"))
            {
                this.build = input.getJSONObject("build");

                if(this.build.has("year")) this.year = this.build.getInt("year");
                else this.year = 1970;

                if(this.build.has("make")) this.make = this.build.getString("make");
                else this.make = "N/A";

                if(this.build.has("model")) this.model = this.build.getString("model");
                else this.model = "N/A";

                if(this.build.has("trim")) this.trim = this.build.getString("trim");
                else this.trim = "N/A";

                if(this.build.has("transmission")) this.transmission = this.build.getString("transmission");
                else this.transmission = "N/A";

                if(this.build.has("drivetrain")) this.drivetype = this.build.getString("drivetrain");
                else this.drivetype = "N/A";

                if(this.build.has("cylinders")) this.cylinders = this.build.getInt("cylinders");
                else this.cylinders = 4;

                if(this.build.has("engine")) this.engine = this.build.getString("engine");
                else this.engine = "N/A";

                if(this.build.has("dist")) this.distance = this.build.getDouble("dist");
                else this.distance = 0;
            }

            if(input.has("dealer"))
            {
                this.dealer = input.getJSONObject("dealer");
                if(this.dealer.has("name")) this.seller_name = capitalizeLetters(this.dealer.getString("name"));
                else this.seller_name = "N/A";

                if(this.dealer.has("city")) this.city = this.dealer.getString("city");
                else this.city = "N/A";

                if(this.dealer.has("state")) this.state = this.dealer.getString("state");
                else this.state = "N/A";
            }

            if(input.has("media"))
            {
                this.img_json = input.getJSONObject("media");
                if(this.img_json.has("photo_links")) this.img_array = this.img_json.getJSONArray("photo_links");
                else this.img_json = null;

                int n = this.img_array.length();
                for(int i=0;i<n;i++)
                {
                    if(i >= 50) break;
                    else
                    {
                        this.images.add(img_array.getString(i));
                    }
                }
            }
        }
        catch(JSONException ex)
        {
            System.out.println("JSON Exception thrown");
        }
    }

    protected CarListing(Parcel in) {
        make = in.readString();
        model = in.readString();
        trim = in.readString();
        vin = in.readString();
        color = in.readString();
        condition = in.readString();
        transmission = in.readString();
        engine = in.readString();
        drivetype = in.readString();
        seller_type = in.readString();
        seller_name = in.readString();
        website = in.readString();
        city = in.readString();
        state = in.readString();
        year = in.readInt();
        price = in.readInt();
        mileage = in.readInt();
        cylinders = in.readInt();
        distance = in.readDouble();
        images = in.createStringArrayList();
        one_owner = in.readByte() != 0;
        clean_title = in.readByte() != 0;
        index = in.readInt();
    }

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

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

    public String capitalizeLetters(String input)
    {
        String[] array = input.split(" ");
        String output = "";
        int n = array.length;
        for(int i=0;i<n;i++)
        {
            String cap = array[i].substring(0, 1).toUpperCase() + array[i].substring(1);
            output += cap;
        }
        return output;
    }

    public void makeHashMap()
    {
        String vehicle_title = Integer.toString(this.year) + this.make + this.model + this.trim;
        String vehicle_information = NumberFormat.getIntegerInstance().format(this.mileage) + " miles | " + this.color + " | " + this.condition + " | $" + NumberFormat.getIntegerInstance().format(this.price);
        String dealer_name = this.seller_name;
        String location = Double.toString(this.distance) + " mi. | " + this.city + ", " + this.state;
        String first_img = this.images.get(0);

        this.listview_hashmap.put("title", vehicle_title);
        this.listview_hashmap.put("information", vehicle_information);
        this.listview_hashmap.put("dealer", dealer_name);
        this.listview_hashmap.put("distance", location);
        this.listview_hashmap.put("first_image", first_img);
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(make);
        dest.writeString(model);
        dest.writeString(trim);
        dest.writeString(vin);
        dest.writeString(color);
        dest.writeString(condition);
        dest.writeString(transmission);
        dest.writeString(engine);
        dest.writeString(drivetype);
        dest.writeString(seller_type);
        dest.writeString(seller_name);
        dest.writeString(website);
        dest.writeString(city);
        dest.writeString(state);
        dest.writeInt(year);
        dest.writeInt(price);
        dest.writeInt(mileage);
        dest.writeInt(cylinders);
        dest.writeDouble(distance);
        dest.writeStringList(images);
        dest.writeByte((byte) (one_owner ? 1 : 0));
        dest.writeByte((byte) (clean_title ? 1 : 0));
        dest.writeInt(index);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 2012-06-20
    相关资源
    最近更新 更多