Reputation: 4371
currently I'm doing something for my project wherein I created a separate Class that will only handle the Asynctask and get the value of the webservices I passed and that class should return the JSON response as a String. Now I already achieved it using taskName.execute().get();
wherein it will wait for the task to complete but the problem is it is also waiting for the task to complete before displaying the screen layout. Making my progressDialog useless and cause a delay on switching screens. Here's my code for now:
For the Class with AsyncTask:
public class UtilGetResponse {
Context context;
Map hash_values = new HashMap();
int DialogType;
String response;
/*
PLAN FOR DialogTypes:
* 0 - Standard Please wait dialog
* 1 - Progress dialog
* 2 - Camera upload dialog
* */
InputStream is = null;
StringBuilder string_builder = null;
public UtilGetResponse(Map values, Context baseContext, int type){
/*initialize class and pass the hash values for parameters*/
context = baseContext;
hash_values.putAll(values);
DialogType = type;
}
public String startTask(){
//TODO CASE WHEN BASED ON THE DIALOG TYPE SPECIFIED
Utilities util = new Utilities();
if(util.isOnline(context)){
try {
new UploaderTaskStandard().execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return response; //THE RESPONSE ONLY SHOW ONCE THE WHOLE TASK IS COMPLETED
}
public class UploaderTaskStandard extends AsyncTask<Map, Void, Void> {
ProgressDialog simpleDialog;
@Override
protected void onPreExecute() {
/*Do something before the async task starts*/
simpleDialog = new ProgressDialog(context);
simpleDialog.setMessage("Please wait");
simpleDialog.show();
}
@Override
protected Void doInBackground(Map... maps) {
uploadData();
return null;
}
protected void onPostExecute(Void v) {
/*Do something after the task is complete*/
simpleDialog.dismiss();
}
}
private void uploadData() {
response = "null";
String url = hash_values.get("url").toString().replace(" ", "%20"); //get the URL replacing the space with %20
//If the user is trying to upload a file use this part
try {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
/*This will convert the hashMap sent into individual part per key per value*/
Set set = hash_values.entrySet();
Iterator iterator = set.iterator();
/*do a loop passing all the data on a string*/
while(iterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry)iterator.next();
String keyword = String.valueOf(mapEntry.getKey());
String value = String.valueOf(mapEntry.getValue());
/*this will check if the passed data is a URL, file or a simple value*/
if(!keyword.equals("url")){
if(value.matches("(.*)/(.*)")){
File file = new File(value);
Log.v("Does this exists?",String.valueOf(file.exists()));
if(file.exists()){
FileBody upload_file;
upload_file = new FileBody(file);
/*not url but file*/
mpEntity.addPart(keyword, upload_file);
}else{
/*not url and not file*/
mpEntity.addPart(keyword, new StringBody(value));
}
}else{
/*not URL and not file*/
mpEntity.addPart(keyword, new StringBody(value));
}
}
}
post.setEntity(mpEntity);
HttpResponse response = client.execute(post);
HttpEntity resEntity = response.getEntity();
is = resEntity.getContent();
} catch (Exception e) {
e.printStackTrace();
response = "null";
}
/*convert JSON to string*/
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
string_builder = new StringBuilder();
String line = "0";
while ((line = reader.readLine()) != null) {
string_builder.append(line + "\n");
}
is.close();
response = string_builder.toString();
}catch(Exception e){
e.printStackTrace();
}
}
}
And to call this:
Map hash_values = new HashMap();
try{
HashMap params = new HashMap<String,String>();
params.put("param1", "YOUR_PARAM");
params.put("url", "YOUR_WEBSERVICE_URL");
//pass parameters
hash_values.putAll(params);
//start async task
UtilGetResponse util = new UtilGetResponse(hash_values, getActivity(), 0);
String result = util.startTask();
Log.v("The result string",result);
}catch (Exception e){
e.printStackTrace();
e.getCause();
Toast.makeText(getActivity(), "Oops problem", Toast.LENGTH_SHORT).show();
}
Is there's a way for me to do this properly without really waiting for the whole task to finish before moving to the next screen? I'm thinking of using a Handler but I'm not really familiar on how to use it anyway.
Upvotes: 0
Views: 385
Reputation: 4344
Your issue is with usage of this
new UploaderTaskStandard().execute().get();
Although you using AsynTask, but still making system wait until result which is against your requirement, what you need is a delivery mechanism, which will notify you back once results are ready. You can take either of two approaches.
change to this, and implement one of below mechanism.
new UploaderTaskStandard().execute();
onResultReady
, and passing an object of class implementing above interface to your method startTask
, and posting result back from AsyncTask onPostExecute
once it is available via interface mechanism.Going via interface will be very easy and in this way your code will be independent of your network logic, sample code below
// Observer listener interface design
interface ResultListener{
// You can overload this method with data type you want to return
public void onResultReceived();
// Use them in a proper way for sending error message back to your program
public void onTaskCancelled();
public void onError();
}
// This will be your new method signature
public String startTask(ResultListener listener){
// Call it liske this, passing listener reference
new UploaderTaskStandard().execute(listener);
}
// This is your AsyncTask model
public class UploaderTaskStandard extends AsyncTask<ResultListener, Void, Void> {
ResultListener listener;
@Override
protected Void doInBackground(ResultListener... maps) {
this.listener = maps[0];
uploadData();
return null;
}
protected void onPostExecute(Void v) {
/*Do something after the task is complete*/
simpleDialog.dismiss();
// Notify back to calling program
listener.onResultReceived();
}
}
Upvotes: 3