I've just started learning about Retrofit 2. I need to consume a RESTful API for an existing Android app. Essentially, the data model for the Android app already exists. I have a REST service which doesn't directly translate to the model classes / properties used by the app (i.e. internally the class properties do not comply with the kind of naming required by Retrofit to work automatically).
For example, given a Car object, the API may return make, model and color. The app's internal model has an existing Vehicle class instead, and property names do not directly map. Moreover, there are certain properties that must be initialized in a particular order.
I know this qualifies for a Custom Converter but would you suggest I instead look into a custom Gson Deserializer? Would that be a better / easier choice instead?
Any guidance would be appreciated as I've just started reading up on Retrofit. I like the fact that I don't have to write all the boilerplate code, yet I feel like I'm unable to utilize its full potential given I need to 'map' all the objects and their properties manually.
There are several things you need to consider:
1) Does you API response keeps the same (even with missing attributes) format
then:
1.1) you can make a custom converter or deserializer
1.2) modify&sync your internal Android model to represent the one you receive or vice versa as if your Android model differ allot it can involve lots of computation on every response
else:
2)if your API responses are in different format and it is really RESTful API then you should have information of the media type by some means in the header or in the body of the response and based on this info you can then choose the appropriate converter/deserializer.
This is more like Custom Converter that delegates to another Converter based on the actual response.
For both scenarios you can apply some kind of in-the-middle converter/mapper after you get response from Retrofit which is possibly the easiest but again it will consume CPU and memory everytime you get a response.
Related
One of the requirements for our native mobile apps is to retrieve a config JSON that can easily be changed during production. For example, in our apps, we will hit up a URL that returns a JSON response containing features that the business wants enable, disabled or list of base URLs:
GET https://ourwebsite.com/mobile_config/
RESPONSE
{
"enableFeatureA": true,
"enableFeatureB": false,
"baseUrls": [
"foo",
"bar"
]
}
To meet the requirement of it being configurable during runtime, we're planning to use a content management system, which has a publishing feature. We've recently been looking into AEM as our new publishing tool. My idea is to save a JSON file into the AEM content manager, and when a GET request is made to the URL, the backend will read the JSON file and return it as an 'application/json' content type. However, I can't find any obvious way to achieve the result of returning the contents of the JSON file when making a request using AEM.
Being fairly new to AEM, my guess is just create a jsp file to read the contents. But how do I return it? How do I manage the 'routes'? Do I need to set up a template? Is this the best approach?
Any guide is appreciated.
AEM reserves the use of .json as an extension; it uses it for RESTful views of content in a JSON format. You might have luck using a different file extension, such as filename.foo - but it'll probably give you the wrong mimetype unless you configure Dispatcher to fix this. This probably isn't the most considerate approach.
In short, if you upload a .json file into the DAM, you won't get what you expect. You'll end up with a path that looks something like /content/xyz/abc.json - but it'll render with the AEM JSON code, and give you the properties from the datastore instead of your file.
It is possible to turn off AEM JSON output, but it tends to break things as noted in the Security Checklist. Besides it tends to be blocked in Dispatcher configuration anyway most of the time (depending on local policy).
One approach, assuming that Dispatcher does allow JSON requests (or that you are able to permit this safely) is to create a JSON.jsp a page or component, and have the JSON data as a property. This also can have side effects in the authoring interface, as the JSON can interfere with the edit dialogues.
I think the best option might be to use static replication to publish the file onto a static webserver. This is done as a separate replication queue. There's a related question here that may help.
I have recently done something pretty much identical to what you are asking. I created a featureToggling AEM component to allow runtime authoring of specific features of standalone angular applications. The angular application looks to the JSON content stored for my featureToggle component as the app initialises and enables/disabled features based on the values stored.
The component itself is a multifield that allows me to add multiple feature types with a toggle switch to turn them on or off. The JSON for ALL AEM pages is actually exposed by appending .infinity.json to the end of the url. My angular app simply reads from and interprets the JSON on initialise then shows/hides features of the app.
EG: http://[mysite]/[featureTogglePagename].infinity.json
In my android app, I need to post JSON data to several REST APIs and get JSON data back for parsing. I want to use GSON to serialize/deserialize the data.
Each REST API has different input/output fields, should I define a separate class to hold data for each API request and response like this?
public class API1RequestData{
public String field1;
public String field2;
}
I am asking this, because if I am using python to construct the JSON request, I don't need to define classes, a dictionary will do.
I believe you should by design (I end up re-using them when I can though). This guarantees you don't send unnecessary data to the server.
If you are really worried about data consumption, i recommend you to:
Do not send null values to the server (just check if they arrive null);
Use integers for errors in the response, instead of booleanor string
Send only new stuff when refreshing some data (save some checksum/timestamp of the "data version" and check it)
...
It all depends on what your application needs. Sometimes it's not worth adding some design patterns that will slow down development in exchange for nothing
I created a base class that has all of the functions for post and get, then I inherit that class and override the collection part of the class. Part of every request is authentication, request type, and request body. Part of every response is response type, permission level, and the data. The data becomes a collection on most of the inherited classes. This works well for serialization and deserialization on both ends and using the base class keeps code maintenance to a minimum.
I've had other projects where I've done things differently for various reasons. Whatever works is good. If you have identically structured requests but the names are what is different, then just make one class and rely on context to know what it is. If the requests are structured differently, use different classes.
For my Android app, I want to keep the network traffic as low as possible (of course).
I'm aware of HttpResponseCache but it only works on API >= 13 so it's not an option for me.
I thought of of using using the LruCache, use the REST Url as the key (given theres no POST data).
When I get a response from the server (JSON) I instantly create POJOs from it with Gson.
What's better to use as the value? The JSON String, then deserialize it again with Gson or to store the POJOs? I know deserializing takes a little cpu time, but perhaps there's a downside to storing the POJOs in my cache?
Say I have an Activity that diplays the content of a POJO called 'Product' (that I got from the server as JSON). On orientation change, can I just forget about keeping the Product POJO (via savedInstanceState or whatever) because the network call to retrieve it again will most probably be 'free' anyway (because it's still in the cache)?
Would it be better to have separate caches for different types of Objects or just use one big cache?
Any advise on how to determine a good size for the cache (in MiB or just number of Entries)
A good place to start is Virgil Dobjanschi's Google I/O 2010 talk on RESTful patterns for Android: http://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html
In a nutshell, he advocates for using SQLite to keep track of the state of your HTTP requests and caching data to minimize requests. I found a sample implementation here, but you may want to search around for more resources on the patterns outlined in that talk.
Since originally answering this, several good open source libraries for Android that will handle caching HTTP requests have come into existence. OkHttp and Volley are two of solid options.
Related to this question on JPA and Android, but looking for design guidance.
I have some data which will be persisted with Objectify on AppEngine. These objects also need to be interacted with on an Android App (and later, an iPhone App). Let's say they are playing cards:
#Entity
public class Card {
#Id Long id;
String suit;
String value;
}
Should I use the exact same class in my Android App as I do in AppEngine, or should I restrict these objects only to the layer closest to the DataStore, and re-encapsulate the data for transmission and use on the mobile - or use a superclass or Interface perhaps?
I suggest that you take the later approach since that will help you build a rich Domain model that is a set of pure classes and not interconnected with any other framework.
One can also refer to these classes as Data Transfer Objects or Value Objects. The nomenclature could be different but the principle is the same i.e. you want data to be passed between different layers of your applications.
Taking this approach of separation will help you a rich Domain model over time and it can be independent of underlying layers and the frameworks that they may use.
Objects persisted thru Objectify have relationships that you may not want to drag with to the client.
Design of API interface (contract) sooner or later will require objects that are different than entity objects. I created two packages, one for Objectify entity and another for api with POJOs and endpoints
I have a REST API which returns JSON to its calls. However, depending on the call I perform, the answer varies. Using Gson will result in a different POJO object for each API response.
Considering I have an IntentService who handles all my GET requests, and I only pass it an URL in the intent, what would be the best way to handle the different responses in the IntentService?
I've been messing around with JSONs in Android for a while, but I can't seem to find an elegant/smart solution for this issue. I've been creating an enum to differentiate the possible API requests, and passing the selected enum value in the intent, in order for the IntentService to choose the action to perform using a switch statement.
Thank you.
If there is a common business logic for all the resulting different POJOs you get, then it would be nice to try to use the same Class, and for this, to try to customize the GSON mapping strategy.
If you don't really have a common logic, then you can consider your GSON objects as DTOs, and then your "mapping" to the business Classes is done on a lower layer (And you have here a lot of ways to do it, including Dozer).
For a more specific answer, more details or examples for your project would help.