Không thể tạo trình chuyển đổi cho lớp của tôi trong thư viện Retrofit của Android


130

Tôi đang chuyển từ sử dụng Volley sang Retrofit, tôi đã có lớp gson mà tôi đã sử dụng trước đây để chuyển đổi phản hồi JSONObject thành một đối tượng thực hiện các chú thích gson. Khi tôi đang cố gắng tạo http nhận yêu cầu bằng cách sử dụng trang bị thêm nhưng sau đó ứng dụng của tôi gặp sự cố với lỗi này:

 Unable to start activity ComponentInfo{com.lightbulb.pawesome/com.example.sample.retrofit.SampleActivity}: java.lang.IllegalArgumentException: Unable to create converter for class com.lightbulb.pawesome.model.Pet
    for method GitHubService.getResponse

Tôi làm theo hướng dẫn trong trang web trang bị thêm và tôi đưa ra các triển khai sau:

Đây là hoạt động của tôi, nơi tôi đang cố gắng thực hiện yêu cầu http http:

public class SampleActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("**sample base url here**")
                .build();

        GitHubService service = retrofit.create(GitHubService.class);
        Call<Pet> callPet = service.getResponse("41", "40");
        callPet.enqueue(new Callback<Pet>() {
            @Override
            public void onResponse(Response<Pet> response) {
                Log.i("Response", response.toString());
            }

            @Override
            public void onFailure(Throwable t) {
                Log.i("Failure", t.toString());
            }
        });
        try{
            callPet.execute();
        } catch (IOException e){
            e.printStackTrace();
        }

    }
}

Giao diện của tôi đã trở thành API của tôi

public interface GitHubService {
    @GET("/ **sample here** /{petId}/{otherPet}")
    Call<Pet> getResponse(@Path("petId") String userId, @Path("otherPet") String otherPet);
}

Và cuối cùng là lớp Pet nên là phản hồi:

public class Pet implements Parcelable {

    public static final String ACTIVE = "1";
    public static final String NOT_ACTIVE = "0";

    @SerializedName("is_active")
    @Expose
    private String isActive;
    @SerializedName("pet_id")
    @Expose
    private String petId;
    @Expose
    private String name;
    @Expose
    private String gender;
    @Expose
    private String age;
    @Expose
    private String breed;
    @SerializedName("profile_picture")
    @Expose
    private String profilePicture;
    @SerializedName("confirmation_status")
    @Expose
    private String confirmationStatus;

    /**
     *
     * @return
     * The confirmationStatus
     */
    public String getConfirmationStatus() {
        return confirmationStatus;
    }

    /**
     *
     * @param confirmationStatus
     * The confirmation_status
     */
    public void setConfirmationStatus(String confirmationStatus) {
        this.confirmationStatus = confirmationStatus;
    }

    /**
     *
     * @return
     * The isActive
     */
    public String getIsActive() {
        return isActive;
    }

    /**
     *
     * @param isActive
     * The is_active
     */
    public void setIsActive(String isActive) {
        this.isActive = isActive;
    }

    /**
     *
     * @return
     * The petId
     */
    public String getPetId() {
        return petId;
    }

    /**
     *
     * @param petId
     * The pet_id
     */
    public void setPetId(String petId) {
        this.petId = petId;
    }

    /**
     *
     * @return
     * The name
     */
    public String getName() {
        return name;
    }

    /**
     *
     * @param name
     * The name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     *
     * @return
     * The gender
     */
    public String getGender() {
        return gender;
    }

    /**
     *
     * @param gender
     * The gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    /**
     *
     * @return
     * The age
     */
    public String getAge() {
        return age;
    }

    /**
     *
     * @param age
     * The age
     */
    public void setAge(String age) {
        this.age = age;
    }

    /**
     *
     * @return
     * The breed
     */
    public String getBreed() {
        return breed;
    }

    /**
     *
     * @param breed
     * The breed
     */
    public void setBreed(String breed) {
        this.breed = breed;
    }

    /**
     *
     * @return
     * The profilePicture
     */
    public String getProfilePicture() {
        return profilePicture;
    }

    /**
     *
     * @param profilePicture
     * The profile_picture
     */
    public void setProfilePicture(String profilePicture) {
        this.profilePicture = profilePicture;
    }


    protected Pet(Parcel in) {
        isActive = in.readString();
        petId = in.readString();
        name = in.readString();
        gender = in.readString();
        age = in.readString();
        breed = in.readString();
        profilePicture = in.readString();
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(isActive);
        dest.writeString(petId);
        dest.writeString(name);
        dest.writeString(gender);
        dest.writeString(age);
        dest.writeString(breed);
        dest.writeString(profilePicture);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Pet> CREATOR = new Parcelable.Creator<Pet>() {
        @Override
        public Pet createFromParcel(Parcel in) {
            return new Pet(in);
        }

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

vui lòng thêm Chuỗi phản hồi của liên kết này mysample.com/development/cutiness
koutuk

@koutuk đó chỉ là một mẫu, btw tôi đã thay đổi bài đăng của mình rồi
Earwin delos Santos

tại dòng nào bạn đang gặp lỗi ....
koutuk

bạn nên xem qua youtube.com/watch?v=gGuUBlzmtPQ video này
koutuk

ohh đó là cái cũ hãy thử truy cập retrofit vuông.github.io/
Earwin delos Santos

Câu trả lời:


217

Trước đó 2.0.0, trình chuyển đổi mặc định là trình chuyển đổi gson, nhưng trong 2.0.0và sau đó trình chuyển đổi mặc định là ResponseBody. Từ các tài liệu:

Theo mặc định, Retrofit chỉ có thể giải nén các phần tử HTTP thành kiểu của OkHttp ResponseBodyvà nó chỉ có thể chấp nhận RequestBodykiểu của nó cho @Body.

Trong 2.0.0+, bạn cần xác định rõ ràng bạn muốn một trình chuyển đổi Gson:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("**sample base url here**")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

Bạn cũng sẽ cần thêm phụ thuộc sau vào tệp lớp của mình:

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

Sử dụng cùng một phiên bản cho trình chuyển đổi như bạn làm cho trang bị thêm của bạn. Trên đây phù hợp với sự phụ thuộc trang bị thêm này:

compile ('com.squareup.retrofit2:retrofit:2.1.0')

Ngoài ra, lưu ý khi viết bài này, các tài liệu trang bị thêm không được cập nhật hoàn toàn, đó là lý do tại sao ví dụ đó khiến bạn gặp rắc rối. Từ các tài liệu:

Lưu ý: Trang web này vẫn đang trong quá trình mở rộng cho các API 2.0 mới.


tôi vẫn đang gặp sự cố
user3475052 22/03/2017

216

Nếu bất kỳ ai cũng gặp phải điều này trong tương lai vì bạn đang cố gắng xác định nhà máy chuyển đổi tùy chỉnh của riêng mình và đang gặp lỗi này, thì cũng có thể do nhiều biến trong một lớp có cùng tên sai hoặc cùng tên. I E:

public class foo {
  @SerializedName("name")
  String firstName;
  @SerializedName("name")
  String lastName;
}

Có tên nối tiếp được xác định hai lần (có thể do nhầm lẫn) cũng sẽ đưa ra lỗi chính xác tương tự.

Cập nhật : Hãy nhớ rằng logic này cũng đúng thông qua kế thừa. Nếu bạn mở rộng đến một lớp cha với một đối tượng có cùng tên được nối tiếp như bạn làm trong lớp con, nó sẽ gây ra vấn đề tương tự.


2
Đây là vấn đề đối với tôi, quên xóa một trường bên trong lớp con mà tôi chuyển sang lớp cha. Cảm ơn người đàn ông!
Vucko

1
Cảm ơn bạn đã cứu tôi khỏi 2 ngày đấu tranh. Tôi đã mắc lỗi tương tự bằng cách khai báo 2 biến có cùng tên nối tiếp.
Valynk

9

Dựa trên nhận xét hàng đầu, tôi đã cập nhật hàng nhập khẩu của mình

implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'

Tôi đã sử dụng http://www.jsonschema2pojo.org/ để tạo pojo từ kết quả Spotify json và đảm bảo chỉ định định dạng Gson.

Ngày nay, có các plugin Android Studio có thể tạo các mô hình dữ liệu của pojo hoặc Kotlin cho bạn. Một lựa chọn tuyệt vời cho mac là Quicktype. https://itunes.apple.com/us/app/paste-json-as-code-quicktype/id1330801220


5

chỉ cần đảm bảo rằng bạn không sử dụng cùng một tên tuần tự hai lần

 @SerializedName("name") val name: String
 @SerializedName("name") val firstName: String

chỉ cần loại bỏ một trong số họ


Cảm ơn bạn, bạn đã cứu ngày của tôi :)
Hemendra Gangwar

4

Trong trường hợp của tôi, tôi đã có một đối tượng TextView bên trong lớp phương thức của mình và GSON không biết làm thế nào để tuần tự hóa nó. Đánh dấu nó là 'thoáng qua' đã giải quyết vấn đề.


Mặc dù điều này sẽ làm cho nó hiển thị, hãy nhớ rằng nó sẽ không hoạt động nếu bạn làm xáo trộn mã (IE, thông qua proguard) và xuất bản nó; thay vào đó tốt hơn để có các chú thích serializedName hoặc Exposed
PGMacDesign

3

@ Bài viết của Silmarilos đã giúp tôi giải quyết điều này. Trong trường hợp của tôi, đó là tôi đã sử dụng "id" làm tên nối tiếp, như thế này:

 @SerializedName("id")
var node_id: String? = null

và tôi đã đổi nó thành

 @SerializedName("node_id")
var node_id: String? = null

Tất cả làm việc bây giờ. Tôi quên rằng 'id' là một thuộc tính mặc định.


1

Điều này có thể giúp ai đó

Trong trường hợp của tôi, tôi đã viết serializedName như thế này

@SerializedName("name","time")
String name,time; 

Nó nên

@SerializedName("name")
String name;

@SerializedName("time")
String time;

0

Này, tôi đã trải qua cùng một vấn đề ngày hôm nay, tôi mất cả ngày để tìm giải pháp nhưng đây là giải pháp cuối cùng tôi tìm thấy. Đang sử dụng Dagger trong mã của tôi và tôi cần triển khai trình chuyển đổi Gson trong ví dụ trang bị thêm.

vì vậy đây là mã của tôi trước đây

@Provides
    @Singleton
    Retrofit providesRetrofit(Application application,OkHttpClient client) {
        String SERVER_URL=URL;
        Retrofit.Builder builder = new Retrofit.Builder();
        builder.baseUrl(SERVER_URL);
        return builder
                .client(client)
                .build();
    }

đây là những gì tôi đã kết thúc với

@Provides
    @Singleton
    Retrofit providesRetrofit(Application application,OkHttpClient client, Gson gson) {
        String SERVER_URL=URL;
        Retrofit.Builder builder = new Retrofit.Builder();
        builder.baseUrl(SERVER_URL);
        return builder
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

chú ý cách không có trình chuyển đổi trong ví dụ đầu tiên và bổ sung nếu bạn chưa khởi tạo Gson, bạn thêm nó như thế này

    @Provides
    @Singleton
    Gson provideGson() {
        GsonBuilder gsonBuilder = new GsonBuilder();

   gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
        return gsonBuilder.create();
    }

và đảm bảo bạn đã đưa nó vào lệnh gọi phương thức để trang bị thêm.

một lần nữa hy vọng điều này sẽ giúp một số người như tôi.


0

Trong trường hợp của tôi, đó là do cố gắng đưa Danh sách bị dịch vụ của tôi trả về vào ArrayList. Vì vậy, những gì tôi đã có là:

@Json(name = "items")
private ArrayList<ItemModel> items;

khi nào tôi nên có

@Json(name = "items")
private List<ItemModel> items;

Hy vọng điều này sẽ giúp được ai đó!


0

Trong trường hợp của tôi, vấn đề là mô hình SUPERCLASS của tôi có trường này được xác định trong đó. Rất ngu ngốc, tôi biết ....

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.