Create generic requests class - java

I want to make a generic requests class for android
public class Requests {
protected JSONObject postRequest(URL url, Map data) {
return null;
}
protected JSONObject getRequest(URL url) {
return null;
}
}
I know that if I want to do a request I must do a background task (Thread or AsyncTask),
but It´s posible to make a asynctask in both methods?, should I use Threads?, a better idea?
Thanks!

Related

How to use RxJava or Observables to listen for a variable change in a different class?

I am attempting to do a login for an android app. My problem is that when I call login from Activity.java, the Service.java method uses call.enqueue from Retrofit and it is async. So I am not able to wait and consume the response in the Activity.java method (so that I can handle what happens next).
Therefore, I decided that if I can setup a listener of some sort to capture when the response object changes, that I can handle what happens next in the app.
I have been looking into RxJava but no examples that I have seen work across multiple classes or seem to actually work properly. It would be extremely helpful to have some basic syntax that I could apply to this that would allow me to consume the login response object so that I can handle what happens next in the application. I am not married to RxJava either so if there is a different way to approach this that will let me consume this object, I'm fine with that. Thanks!!
GlobalData.java
public class GlobalData {
public static LoginResponse globalResponse;
}
Activity.java
public class Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// Can I subscribe here and do some logic for when globalResponse changes?!?
}
public void login() {
// create login request object
// ...
// call service method
LoginResponse response = service.loginMethod(request);
// Can I await the async in loginMethod so that I run logic after the call?
}
}
Service.java
public class Service implements ServiceInterface {
#Override
public loginMethod(LoginRequest request) {
// Setup Retrofit for api call
// ...
Call<LoginResponse> call = apiService.login(request);
// async call to get a response from the api for login
call.enqueue(new Callback<LoginResponse>() {
#Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
GlobalData.globalResponse = response.body(); // updates global data variable with the response from login
}
}
}
}
Check the next blogs to know how use Rx and retrofit together
Rxjava & Retrofit: http://www.baeldung.com/retrofit-rxjava
How subscribe an observable object: http://www.vogella.com/tutorials/RxJava/article.html#creating-observables-subscribing-to-them-and-disposing-them
I think with that you can continue with you login flow
public class Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// Can I subscribe here and do some logic for when globalResponse changes?!?
Yes, but only if you use a BehaviorSubject/BehaviorRelay (I vote Relay, see BehaviorRelay).
So you have
public class GlobalData {
private GlobalData() {}
public static LoginResponse globalResponse;
}
But it should be something like
public class GlobalData {
private GlobalData() {}
public static BehaviorRelay<Optional<LoginResponse>> globalResponse = BehaviorRelay.createDefault(Optional.absent());
}
And
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
LoginResponse login = response.body();
if(login != null) {
GlobalData.globalResponse.accept(Optional.of(response.body());
}
}
Bonus points if you hide the Relay and expose a method that writes into it, and another that shows it as Observable<Optional<T>>.
Anyways now you can do
Disposable disposable = GlobalData.globalResponse.subscribe((opt) -> {
if(opt.isPresent()) {
LoginResponse data = opt.get();
// do whatever
}
});

DRY: a case with AsyncTasks

I'm developing an Android app which has a lot of different requests for web services.
Every request is done in a subclass of AsyncTask in this manner:
(new AsyncTask<String, Void, Object1>() {
#Override
protected Object1 doInBackground(String... params) {
// network request and parsing to Object1
Object1 obj = new Object1();
obj1 = Parser.parseObject1(httpClient.execute(...));
return obj1;
}
#Override
protected Object1 onPostExecute(Object1... ret) {
return ret[0];
}
}).execute();
Object1 is a placeholder for different objects (Car, Bicycle, Truck...), each one in a different AsyncTask.
What are my alternatives other than returning the output of httpClient in a String and parsing in the Main Thread (UI Thread)? Avoid parsing in the UI Thread sounds reasonable if it's going to parse a lot of data, am I right?
-= UPDATE =-
Let me rephrase the question: I'm asking for a more intelligent way to develop my application avoiding being repetitive (AsyncTask has a lot of boilerplate code). The way I did was by creating 20+ subclasses of AsyncTask, which clearly is not DRY (do not repeat yourself).
In iOS we have lambda expressions so callbacks done in web requests are very easy and succinct.
You can create classes that contain most of your boilerplate code. E.g.
public class SpecialAsyncTask<T> extends AsyncTask<String, Void, T> {
public interface ResultProvider<T> {
T generateResultInBackground(String... params);
}
public interface ResultConsumer<T> {
void handleResultInForeground(T result);
}
private final ResultProvider<T> mProvider;
private final ResultConsumer<T> mConsumer;
private SpecialAsyncTask(ResultProvider<T> provider, ResultConsumer<T> consumer) {
mProvider = provider;
mConsumer = consumer;
}
#Override
protected T doInBackground(String... params) {
return mProvider.generateResultInBackground(params);
}
#Override
protected void onPostExecute(T result) {
mConsumer.handleResultInForeground(result);
}
public static <T> void execute(ResultProvider<T> provider, ResultConsumer<T> consumer, String... params) {
new SpecialAsyncTask<T>(provider, consumer).execute(params);
}
}
is an example how you could keep Object1 as a generic parameter while being able to specify an object that only needs to implement an interface to handle code that would otherwise have to be inside a new AsyncTask instance.
With a schema like that you could for example define some common code as static content:
class Providers {
public static final ResultProvider<String> HTTP_GETTER = new ResultProvider<String>() {
#Override
public String generateResultInBackground(String... params) {
return MagicHttpLibrary.getContentAsString(params[0]);
}
};
}
And you can just use Providers.HTTP_GETTER as parameter instead of implementing doInBackground. Or create a new class hierarchy of that implement one of those interfaces with different methods to access them (like factories for example)
Use of above example would look for example like below
class User extends Activity implements ResultConsumer<String> {
#Override
protected void onCreate(Bundle savedInstanceState) {
SpecialAsyncTask.execute(Providers.HTTP_GETTER, this , "http://google.com");
SpecialAsyncTask.execute(Providers.HTTP_GETTER, this , "http://yahoo.com");
}
#Override
public void handleResultInForeground(String result) {
Toast.makeText(this, result, Toast.LENGTH_LONG).show();
}
}
and there is more or less no repeated code besides the different method calls. It depends on how you want to use a class and what actually changes in the code to know how to design something like that. Identify the parts that need to be parametrized and move code that repeats into a re-used place (inheritance / composition).
Google's Volley HTTP request library does the request and parsing both in the same worker thread. So, that's a pretty good example to code by.

Return Multiple Data from AsyncTask

I'm trying to organize my app code separating AsyncTask classes from Activity or Fragments.
Surfing this forum I've learned about the "interface and listener" solution:
Interface.java
public interface TaskCompleteListener<T> {
public void onTaskComplete(T result);
}
AsyncTask.java
[...]
#Override
protected void onPostExecute(String JSONResponse) {
// using Gson library I convert JSONResponse string to POJO objects...
listener.onTaskComplete(result);
}
Activity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// start AsyncTask...
}
// Inner class implementing interface
public class LoadTaskCompleteListener implements TaskCompleteListener<Object> {
#Override
public void onTaskComplete(Object result) {
updateUI(result);
}
}
public void updateUI(Object result) {
// here you can manage UI updating, using result object
}
}
UPDATE
DataHelper.java
public class DataHelper {
private AsyncTaskCompleteListener<Object> listener;
public DataHelper(AsyncTaskCompleteListener<Obejct> listener) {
this.listener = listener;
}
// Multiple AsyncTask are defined here...
}
Well, I like this pattern so much, but: what if inside activity (or fragment)
I have multiple requests, with different type of results (single object, array, list)
and different business logic for managing them?
I can't handle that using a single callback. Any ideas? Should I add multiple
callbacks inside the interface? I'm really stuck with this.
I've a single file called DataHelper with multiple AsyncTask inside (something like web getters).
Naturally I can give up with this approach if you suggest any other alternative.
Why not return an array of Objects as a result? Then if you have more than one object inside that array you'll know the order in which you put them so you can use more than one set of results at a time.
public interface TaskCompleteListener<T> {
public void onTaskComplete(T... results);
}
Note that a 'handler' can be used instead of an async task and that each handler may return its message to the message looper with the msg wrapping different data. Easy to handle many data types because its just a message component.
Sample here
See 'process_entity() ' where the messages containing result component are sent by sample code.
Note that the definition of onTaskComplete() accepts as argument a generic type, type T:
onTaskComplete(T result);
this means that you can pass in any object type, single object, array, list, etc.
Regarding on how to handle different results using a single callback, you can use a Bundle to put the result in, associated with a key, and then in updateUI() check for that key and take appropriate actions.
Something like this (pseudocode, not sure if it will compile):
#Override
protected void onPostExecute(String JSONResponse) {
Bundle bundle = new Bundle();
bundle.putString("key_json_response", result); //put the response in a Bundle
listener.onTaskComplete(bundle);
}
// .....
public void updateUI(Object result) {
Bundle bundle = (Bundle)result;
if(bundle.containsKey("key_json_response")){
String json = bundle.getString("key_json_response");
// process json
} else if(bundle.containsKey("key_another_response")){
// process another response
}
}

Best way to organize AsyncTask

I am a relatively new Android developer and am working on an application right now that makes a lot of calls to a RESTful web service.
I am making each call in an asyncTask but in some files, the amount of different async tasks I have approaches 15. Right now I have them all as private classes inside my activity class. How can I organize them better(i.e. put them in separate files) while still being able to update the UI.. I was thinking of passing the context into the constructor of each asyncTask but I was just wondering if there was a best practice/better way.
Thanks!
Instead of using so many classes for different types of asynctask , I suggest you use this library
you can have a look at here
http://loopj.com/android-async-http/
your code will become very very less , instead of declaring so may asynctask seperately writing bulk of code , you can just use 4 lines of code
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
System.out.println(response);
}
});
I is very efficient in geting the response very quickly.
I hope this will help you out. :)
Passing in the Activity as a constructor parameter sounds like a good plan to me. Basically the same is happening when you declare them as an inner class.
But keep in mind, that there are some drawbacks for using AsyncTasks to load data. Once started, they will continue to run even when the activity is already closed and hold a reference to your activity (it can therefore not be garbage collected).
You may want to look into other concepts like loaders.
Consider using a library to simplify your code base. I wrote droidQuery which, among other things, can be used to simplify AsyncTasks. For example, to get JSON data from example.com, and to have access to context afterwards, you can do this:
$.ajax(new AjaxOptions().url("http://www.example.com")
.context(this)
.type("GET")
.dataType("json")
.success(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
JSONObject json = (JSONObject) params[0];
Context context = droidQuery.context();
//TODO:
}
})
.error(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
AjaxError error = (AjaxError) params[0];
Log.e("Ajax", "Error " + error.status + ": " + error.reason);
}
}));
For lots of different requests that you call a lot, you can also create instances of AjaxOptions for later use, which have different URLs, types, dataTypes, etc:
Map<String, AjaxOptions> requests = new HashMap<String, AjaxOptions>();
//add the example above:
requests.put("example", new AjaxOptions().url("http://www.example.com")
.context(this)
.type("GET")
.dataType("json")
.success(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
JSONObject json = (JSONObject) params[0];
Context context = droidQuery.context();
//TODO:
}
})
.error(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
AjaxError error = (AjaxError) params[0];
Log.e("Ajax", "Error " + error.status + ": " + error.reason);
}
}));
Then later, just perform this task by calling:
$.ajax(requests.get("example"));

Networking in Android/Java - how do I callback to a API class after a call back from the server?

So I'm writing an Android application in Java based on an iOS application that I am also working on, but this question is more asking about how to communicate callback mechanism (like blocks in Objective-C 2.0) in Java.
This application involves networking, authenticating and communicating with a server via an API.
I am using this framework: https://github.com/loopj/android-async-http
I am trying to encapsulate all of the networking model into classes to make everything clean and easy (it seems so easy in iOS with delegates and blocks, but java doesn't appear to have ANY of these conveniences). So, I am using this as a guide for callbacks: http://www.gdgankara.org/2013/03/25/android-asynchronous-http-client-a-callback-based-http-client-library-for-android-and-android-smart-image-view/
Now lets say I don't want to make a call from an Activity class, but an API class, which can be called from an Activity class, how can I do this? I know easily how to do this with blocks and delegates in iOS, but how can I do this with interfaces?
For Example:
In iOS (using a common networking framework called AFNetworking), I have 4 classes:
HTTPClient.h/m
+(id)sharedHTTPClient
{
static dispatch_once_t pred = 0;
__strong static id __httpClient = nil;
dispatch_once(&pred, ^{
NSString *baseURL = http://baseurl.com;
__httpClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:baseURL]];
[__httpClient setParameterEncoding:AFJSONParameterEncoding];
});
return __httpClient;
}
APILogin.h/m
-(void)loginWithSuccessBlock:(void (^)(NSArray *responseArray))loginSuccess {
HTTPClient *httpClient = [HTTPClient sharedHTTPClient];
NSURLRequest *request = [httpClient requestWithMethod:#"GET" path:#"/api/login" parameters:nil];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSArray *response = [self.jsonParser parseResponseFromJSON:JSON];
if (loginSuccess) {
loginSuccess(response);
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
[APIErrorHandler handleError:error withHTTPResponse:response];
}];
[operation start];
}
LoginObject.h/m
-(id)init
{
self = [super init];
if(self) {
[self.apiLogin loginWithSuccessBlock:^ void (NSArray *loginArray) {
//process the array
}];
}
}
LoginVC.h/m
...
LoginObject *loginObj = [[LoginObject alloc] init];
...
So, now what I have so far, using the Android-Async-Http library is:
HTTPClient.java
public class HTTPClient extends AsyncHttpClient {
public static HTTPClient sharedHTTPClient;
public static String baseUrl = "http://baseurl.com";
public HTTPClient {
super();
}
...
}
APILogin.java
public class APILogin {
public void loginWithSuccessBlock() {
HTTPClient httpClient = QHTTPClient.sharedHTTPClient;
httpClient.get("/api/login", new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONArray response) {
// Successfully got a response
ArrayList<LoginObject> loginInfo = this.jsonParser.parseLoginFromJSON(response);
**NEED TO DO A CALL BACK!! Like with the blocks in iOS**
}
#Override
public void onSuccess(JSONObject response) {
// Successfully got a response
// shouldn't be an object
throw new IllegalArgumentException();
}
#Override
public void onFailure(Throwable e, String response) {
// Response failed :(
}
});
}
LoginObject.java
public class LoginObject {
public LoginObject {
this.apiLogin.loginWithSuccessBlock(**something something for a callback**);
}
}
Hopefully, I've made it a little clearer what I am trying to achieve. I want to be able to execute some kind of callback block on the object that called the api call, on success. However, it will not always be the same object. LoginObject may have an instance of APILogin.java and so might a different object, so I can't use the second link above in which you can specific a specific class and pass it in and call a method on it, because the classes will be of different types, and Java doesn't have a generic pointer (id or void*) object.
So I've discovered my own answer after trying many things and scouring the web for a possible solution. What I've come up with is to basically chain the response handlers.
So for:
public class APILogin {
public void loginWithSuccessBlock(**final JsonHttpResponseHandler handler**) {
HTTPClient httpClient = QHTTPClient.sharedHTTPClient;
httpClient.get("/api/login", handler);
}
}
public class LoginObject {
public LoginObject {
this.apiLogin.loginWithSuccessBlock(new JsonHttpResponseHandler(){
...
);
}
}
which isn't very robust because it doesn't let me do much customization, but it'll do.

Categories