Использование Retrofit 2 Для получения и извлечения неизвестного набора данных - PullRequest
0 голосов
/ 16 октября 2018

Retrofit - это замечательная библиотека, она проста в использовании и обслуживании, но у меня другой случай, как мы знаем, мы должны применить этапы создания api и отклика модификации соответственно,

экземпляр дооснащения:

retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(new ErrorCallAdapter.MyCallAdapterFactory())
                .client(httpClient)
                .build();
        return retrofit;

Интерфейс API:

 @GET("api/getTheResults")
 ErrorCallAdapter.MyCall<GeneralResponse<SomeEntity> getGenericMethod();

часть ErrorCallAdapter:

@Override
        public void enqueue(final MyCallback<Object> callback) {
            call.enqueue(new Callback<GeneralResponse<T>>() {
                @Override
                public void onResponse(final Call<GeneralResponse<T>> call, final Response<GeneralResponse<T>> response) {
                    final int code = response.code();
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (response.isSuccessful()) {
                                if (response.body().getStatus() == 1) {
                                    callback.onResult(response.body().getResponse());
                                } else
                                    callback.onError(response.body().getMError());
                            } else
                                callback.onError(new MError(code,
                                        response.message() != null ? response.message() : "onResponse error"));
                        }
                    });
                }

                @Override
                public void onFailure(Call<GeneralResponse<T>> call, Throwable t) {
                    if (t != null)
                        callback.onError(new MError(501,
                                t.getMessage() != null ? t.getMessage() : "unexpected error"));
                    else
                        callback.onError(new MError(501,
                                "unexpected error"));
                }
            });

        }

часть выборки данных:

public void loadUserSetupData() {
        ErrorCallAdapter.MyCall<GeneralResponse<Data>, Data> DataCall = apiManager.getData();
        setupDataMyCall.enqueue(new ErrorHandlingCallAdapter.MyCallback<Data>() {
            @Override
            public void onResult(Data data) {
                endProgressDialog();

                apiResult.onSuccess(data);
            }

            @Override
            public void onError(MError mError) {
                endProgressDialog();
                apiResult.onError(mError.getErrorMessage(mContext));
            }
        });
    }

Данные, которые я пытаюсь получить, представлены в формате JSON:

{
    "Status": 1,
    "Error": null,
    "ResponseList": [
        {
            "ErCode": 0,
            "Masseg": null,
            "DType": "OnceData",
            "Contents": {
                "VList": [{
                    "name":"name"
                    "name":"name"
                    "name":"name"
                  }],
                "WList": [{
                    "name":"name"
                    "name":"name"
                    "name":"name"
                  }, {
                    "name":"name"
                    "name":"name"
                    "name":"name"
                  }],
                "UList": [{
                    "name":"name"
                    "dd":"ddd" "DobledataType"
                    "object":"name"  "object data type"
                  }, {
                    "name":"name"
                    "int":"1"
                    "code":"15.00" "float data type
                  }],

            }
        }
    ]
}

«Выше я называю« имя »как объект сущности (каждый из UList, VList, WList - это объекты только для иллюстрации).

Мой вопрос таков: как я могу сделать, чтобы модификация работала для любого типа данных, когда он будет извлекать объект, независимо от его типа, значит, я не знаю, будет ли в списке «Содержимое» объект определенного типа,Я хочу, чтобы он работал так, чтобы я мог получать любой тип, какой бы он ни был, не зная объекта, мы можем указать msg, DType (в предыдущем случае мы знали, что DType = data, например, будет выполнять какое-то действие), но мы не знаемчто тТип объекта ответа (массив строк, объектов, целых чисел или только одной строки) Как мы это делаем в модифицированной Android?

1 Ответ

0 голосов
/ 17 октября 2018

Если вы вообще не можете знать, что такое содержимое поля «Содержимое», вы можете установить его непосредственно как JSONObject в вашей модели, но тогда вам придется выполнять какую-то работу каждый раз, когда вы хотите получить что-тоиз поля содержимого.

Однако, если вы знаете, какой тип он может иметь, например, вы точно знаете, что это будет массив String, String или int, то у вас есть решение использоватьпользовательский десериализатор GSON .

Сначала вам нужно будет изменить модель / Pojo для обработки всех типов, например:

abstract class Model {
    // put here all the fields you know the type is stable
}

// for when content is a list
public class ListModel extends Model {
    @SerializedName("Contents")
    List<String> content;
}

// for when content is a String
public class StringModel extends Model {
    @SerializedName("Contents")
    String content;
}

// add every other derived class you need for the other types that the content field can have

Теперь вы можете создать десериализаторкоторый вернет правильный объект Model:

public class ModelDeserializer implements JsonDeserializer<Model> {
    @Override
    public Model deserialize(JsonElement json, Type typeOfT, 
                             JsonDeserializationContext context) 
                             throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();

        // get the "contents" field
        JsonElement contents = jsonObject.get("Contents");
        if (contents != null) {
            if (contents.isJsonArray()) { // if this is a list, parse as ListModel
                return context.deserialize(jsonObject, 
                    ListModel.class);
            }
            if (contents.isJsonPrimitive()) { // json primitives are number, string, bool, character
                if (contents.getAsJsonPrimitive().isString() {
                    return context.deserialize(jsonObject, StringModel.class);
                }
            }
            // do the same for every other type you might have
        }
        return null;
    }
}

и, наконец, вам придется указать Retrofit и Gson использовать этот десериализатор:

Gson gson = new GsonBuilder()
         .registerTypeAdapter(Model.class, new ModelDeserializer())
         .create();

// just add the new gson object to your converterfactory
retrofit = new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(new ErrorCallAdapter.MyCallAdapterFactory())
            .client(httpClient)
            .build();
    return retrofit;

, и он должен работать.

...