Reputation: 6547
I'm using Retrofit and I've created my ItemTypeAdapterFactory
class that implements TypeAdapterFactory
and create the read method... and everything works great, in my "response"/"data" (json
) there is an array of object.
But I can see that it is very slow! I have an array of 1000/1500 object,
and all the bootelneck is in my ItemTypeAdapterFactory
because it goes
into the "read" method as much as there are object, and looking at the
log, it spends 10-15 seconds into the reading, and after it my
`recyclerview get filled with data.
I'm sure the bottelneck is in the read method being called as many times as my array size, because consuming the same API with POSTMAN, it give me the response in half second.
Is there any faster way of implementing it? I receive response from using google like this:
{
"message": {
"response": : {
"myArray": [
"object 1" : {...},
....,
"object 1500" : {...}
]
},
"status": "101",
"statusmessage":"Record is inserted!"
},
"kind":"....",
"etag":" .... "
}
So I use the ItemTypeAdapterFactory class in order to process the response which comes exactly in this form as JSON, and I get with retrofit everything inside "message" which is the only thing I'm interested in.
This is the code for calling ItemTypAdapterFactory before building the restAdapter in retrofit:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new ItemTypeAdapterFactory())
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();
And my ItemTypeAdapterFactory is this:
public class ItemTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
if (jsonObject.has("message") && jsonObject.get("message").isJsonObject()) {
jsonElement = jsonObject.get("message");
}
}
return delegate.fromJsonTree(jsonElement);
}
}.nullSafe();
}
}
How can I make my retrofit call faster with this AdapterFactory settings? Thanks!
Upvotes: 0
Views: 400
Reputation:
Take a look at this:
Factories should expect create() to be called on them for many types and should return null for most of those types.
Upvotes: 1
Reputation: 32016
It is worse than that, you are calling read
for every element because you are returning a your TypeAdapter
for all types. In your create
method you should only return a new adapter for the type you are interested in, and null for others. From the TypeAdapterFactory
docs --
Factories should expect create() to be called on them for many types and should return null for most of those types.
It will look something like --
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
if(type.getType != Item.class) {
// Do not use custom adapter for other types
return null;
}
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
// your adapter code
}
Upvotes: 1