WordPress Websites for Engineers: Elevate Your Brand
The Lazy Programmers Guide to Consuming Web Services (in Android
1. The Lazy Programmers Guide to Consuming Web
Services (in Android)
Max Bhuiyan http://au.linkedin.com/in/mamnun
Ben Kenny http://au.linkedin.com/pub/ben-kenny/3a/b9a/b67
2. Disclaimer
These slides are available under the Creative
Commons Attribution-ShareAlike (BY-SA) 3.0
License.
Trademarks and brands are the property of their respective
owners.
This presentation is not affiliated with Yahoo, Yahoo7 or Seven
Media.
3. Web API integration challenges
● Authentication
● Response
deserialization
● Caching
● Unreliable Network
4. Android specific challenges
● Network calls on background thread
o Async Tasks
o Loader
o Service/Daemon
● Response Processing : CPU + Memory
constraint
7. : Cache Manager
● Uses an AndroidService to execute network
requests in background
● Plugin Architecture
● Supports request queue & prioritization
● Per request caching policy
● Handles activity/fragment lifecycle
8. Jackson : JSON Processor
● FAST!!!
● Streaming parser
● Easy annotation
based mapping
● Handles
polymorphic
types(more about
this from Ben)
9. RetrofitRetrofit
● Super simple API definition
o 2 lines to define an endpoint
o 1 class with 3 functions to code the Request
● Uses OkHttp(uses nio)
14. Define Model and API interface
@JsonIgnoreProperties(ignoreUnknown = true)
public class Key {
public int id;
@JsonProperty(“key”)
public String publicKey;
public static class List extends ArrayList<Key>{}
}
public interface GithubAPI {
@GET("/users/{user}/keys")
Response userKeys(@Path("user") String user);
}
15. Subclass RetrofitSpiceService
public class GithubService extends RetrofitSpiceService {
@Override
public void onCreate(){
super.onCreate();
addRetrofitInterface(GithubAPI.class);
}
@Override
public CacheManager createCacheManager(Application application) throws
CacheCreationException {
return new CacheManager().addPersister(new
JacksonRetrofitObjectPersisterFactory(application, null));
}
@Override
protected String getServerUrl() { return “https://api.github.com”; }
@Override
protected Converter createConverter() { return new JacksonConverter(); }
}
17. Define Request class
public class GithubUserKeyRequest extends RetrofitSpiceRequest<Key.List.class,
GithubAPI.class> {
private final JsonReader jsonReader = new JsonReader();
private final ObjectMapper objectMapper = new ObjectMapper();
private final String user;
public GithubUserKeyRequest(String user) {
super(Key.List.class, GithubAPI.class);
this.user = user;
}
@Override
public Episode.List loadDataFromNetwork() throws Exception {
Response response = getService().userKeys(user);
Object result =
this.jsonReader.parse(response.getBody().in()).read("$.");
response.getBody().in().close();
return (Key.List)this.objectMapper.convertValue(result, Key.List.class);
}
}
18. Spice up your life!
public class UserKeyFragment extends Fragment {
private final GithubSpiceManager spiceManager = new GithubSpiceManager();
@Override
public void onStart() {
super.onStart();
spiceManager.start(getActivity());
spiceManager.execute(new GithubUserKeyRequest("snookle"), "cacheKey",
1000 * 60, new RequestListener<Key.List>() {
@Override
public void onRequestFailure(SpiceException e) {
Toast.makeText(getActivity(), e.getMessage(),
Toast.LENGTH_LONG).show();
}
@Override
public void onRequestSuccess(Key.List keys) {
// do cool stuff here????
}
});
}
}
19. Gotchas
▪ Request converter and Cache converter are separate and defined in
different classes
▪ JSON weirdness: “null”/null, and true/false/0/1
▪ spiceManager.isDataInCache() will cause a deadlock if called from
Activity/Fragment onStart().
▪ Inner classes must be declared static to access without an instance of
outer class.
› BAD: public class List extends ArrayList<Key>{}
› NOT VERY HELPFUL EXCEPTION: JsonMappingException: No
suitable constructor found for type [simple type, class
com.example.github.Key.List]: can not instantiate from
JSON object (need to add/enable type information?)
› BETTER: public static class List extends
ArrayList<Key>{}