I've already developed many Android apps that make web service requests, always with the following approach:
In every activity that need to make a web service request, I define an inner AsyncTask that shows a ProgressDialog in onPreExecute(), makes the web service call in doInBackground, and dismisses the progressDialog and updates the results in the UI from onPostExecute().
My concern is: Is there a better (shorter) way to do it? Does it make sense to repeat all that code in every activity? I've been googling a lot, but I've found nothing.
My question is: Couldn't I define a Callback interface? for example this one:
public interface RequestCallback {
public void onSuccess(Whatever whatever);
public void onError(ErrorCode errorCode, String message);
}
... and then define an external class, for example AsyncRequest, that wraps the AsyncTask definition and the ProgressDialog show() and dismiss() statements. So, all activities would just need to instantiate that class, and pass in the following parameters:
1) The method of the web service to run
2) A Bundle with all the parameters of that method of the web service
3) A RequestCallback instance (that could be an anonymous inline instance, where I could update the UI from onSuccess())
4) The context of the Activity (necessary to show the ProgressDialog(), so I would still need a way to prevent configuration change exceptions and so...),
Do you find this a good design? It could save hundreds of lines of code...
Your approach is what I did on my project. And it saved a lot of code as you said, I don't have any complaint about it. But here is some issues that I want to tell you:
AsyncTask every time you do a background thread to avoid to pile callback.For the progress dialog, I use it as Singleton, because you don't show many dialogs at the same time. The dialog will be showed when you call the background job, and will be dismiss in the callback. Here is what I did:
private void showProgressDialog(String strMess){
if(null == progressDialog){
progressDialog = new ProgressDialog(MainActivity.this);
}
if(!progressDialog.isShowing()){
progressDialog.setMessage(strMess);
progressDialog.show();
}
}
private void hideProgressDialog(){
if(null != progressDialog && progressDialog.isShowing()){
progressDialog.dismiss();
}
}
void someMethod(){
showProgressDialog("Loading...");
doBackgroundJob(param, new RequestCallBack() {
public void onRequestCompleted(String message, boolean isSuccess) {
hideProgressDialog();
if(isSuccess){
}else{
//do something on error
}
}
});
}
It is an optional, I defined an interface to notify instead of specific class, for each response I use one class, so in base class, I don't care what the response is. Here is it:
public interface OnRequestCompleted<TResponse> {
void requestCompleted(TResponse response);
}
public abstract class BaseRequest<TResponse> implements IRequest{
protected OnRequestCompleted<TResponse> delegate;
protected Class<TResponse> responseClass;
@Override
public void send() {
new HttpTask().execute();
}
private class HttpTask extends AsyncTask<Void, Void, String> {
//...
@Override
protected void onPostExecute(String result) {
if (null != response && null != delegate) {
delegate.requestCompleted(response);
}
}
}
// the response example
public class GroupResponse {
public static class Clip {
public int clipId;
public String detail;
}
public static class Movie {
public int movieId;
public String detail;
}
}
In the subclass of BaseRequest, I will tell it exactly what the response class is (Movie, Clip...)
Hope this help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With