Android Async tasks reuse - java

I am developing an app where in a number of the activities I need to retrieve data via Http.
Once I have the data I process it in the onPostExecute() callback method.
This works fine if I define the async task as an inline class, but as I want to do the same processing in a number of activities I have defined it as an external class.
So the question is, using an external class how do I signal an "event" back to the calling class as a means of passing the data back. I know how to do this in C# but I am new to Java and can not see how to achieve this.

While it is true that a Listener technically correct, I would claim that it is either too complicated or not complicated enough.
Here's an easier solution:
class Foo {
class Bar extends AsyncTask<Void, Void, Result> {
public void onPostExecute(Result res) {
doSomething(res);
}
}
public void doSomething(Result res) {
/// process result
}
public void startTask() {
new Bar().execute();
}
}
Is equivalent to:
class Bar extends AsyncTask<Void, Void, Result> {
private final Foo foo;
public Bar(Foo foo) { this.foo = foo; }
public void onPostExecute(Result res) {
foo.doSomething(res);
}
}
class Foo {
public void doSomething(Result res) {
/// process result
}
public void startTask() {
new Bar(this).execute();
}
}
... which is what you asked: when you pull the inner class out, you lose the implicit pointer. Just make it explicit and pass it in.
The bad news is that there are all sorts of memory leak and lifecycle issues that arise from this solution. I would very much recommend that, before your program gets even bigger, you looking into using an IntentService instead of an AsyncTask and use a Handler, or Activity.runOnUiThread to get the results back onto the UI thread.

One approach:
Define a parent abstract class called ParentActivity (extend Activity of course). Have that contain an abstract method called onAsyncCallback();
Have each class that uses the task to extend that class and implement the method.
In your AsyncTask constructor, have it accept in a ParentActivity.
Eg
ParentActivity activity;
public MyTask (ParentActivity myActivity)
{
this.activity = myActivity;
}
When done in onPostExecute(), simply do
activity.onAsyncCallback(data);
This would also work with an interface, it does the same thing, except intead you have the Constructor accept in the Listener instance.

If you want to do it in a clean way try following approach
First create an enum which contains all your async call names
public enum TaskType {
USER_LOGIN(1), GET_PRODUCTS(2), GET_EMPLOYEE(3);
int value;
private TaskType(int value) {
this.value = value;
}
}
Then create an interface
public interface AsyncTaskListener {
public void onTaskCompleted(String result, TaskType taskType);
}
Now implement this interface in the activity which you are going to call the GetAsyncTask
eg:-
public class LoginActivity extends Activity implements AsyncTaskListener {
protected void onCreate(Bundle savedInstanceState) {
String url = ".....";
new GetAsyncTask(LoginActivity.this, LoginActivity.this, TaskType.USER_LOGIN).execute(url);
}
...
public void onTaskCompleted(String result, TaskType taskType) {
if(taskType == TaskType.USER_LOGIN){
//your login result handling here
}
}
Lastly, this is your AsyncTask
public class GetAsyncTask extends AsyncTask<String, Void, String> {
String outputStr;
ProgressDialog dialog;
Context context;
AsyncTaskListener taskListener;
TaskType taskType;
public GetAsyncTask(Context context, AsyncTaskListener taskListener, TaskType taskType){
this.context = context;
this.taskListener = taskListener;
this.taskType = taskType;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(context, "Loading", "Please wait...", true);
}
#Override
protected String doInBackground(String... params) {
String urlString = params[0];
try {
URL url = new URL(urlString);
HttpURLConnection conn
= (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
if (conn.getResponseCode() != 200) {
throw new IOException(conn.getResponseMessage());
}
// Buffer the result into a string
BufferedReader rd = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
String jsonStr = sb.toString();
outputStr = jsonStr;
} catch (SocketTimeoutException e) {
outputStr = "timeout";
}catch(Exception e){
e.printStackTrace();
outputStr = "error";
}
return outputStr;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
taskListener.onTaskCompleted(result, taskType);
dialog.dismiss();
}
}

Use Listener pattern. Take a look here TaskListener, Task that uses this listener and fragment that calls task

Try making your own http requesting class that extends AsyncTask and than put your code in "doInBackground" call. Thyt way you only have to instantiate your class with url and params and read response. That worked for me.
Here is example:
public class HttpRequest extends AsyncTask<String, Void, String> {
public String url;
public List<NameValuePair> nameValuePairs;
public String httpResponse =null;
public HttpRequest(String _url, List<NameValuePair> _nameValuePairs) {
url = _url;
nameValuePairs=_nameValuePairs;
}
#Override
protected String doInBackground(String... params) {
httpResponse = getWebPageWithFormData(url, nameValuePairs);
return "";
}
public static String getWebPageWithFormData( String url, List<NameValuePair> nameValuePairs ){
String html = "";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
if (nameValuePairs!=null){
try {httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));}
catch (Exception e){}
}
HttpResponse response = null;
try {
response = httpclient.execute(httppost);
}
catch (ClientProtocolException e) { return ""; }
catch (IOException e) { return ""; }
int responseCode = response.getStatusLine().getStatusCode();
switch(responseCode) {
case 200:
HttpEntity entity = response.getEntity();
if(entity != null) {
try{ html = EntityUtils.toString(entity);}
catch (Exception e) {}
}
break;
}
return html;
}
}

Related

Android Studio - download JSON data from 2 urls in one Async Task

I can download data using the downloadJSON class for 1 URL using the below code no problem, but I want to get another set of data so it can be displayed with the other. I've tried several different method but to no avail.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_json);
TextView textView = (TextView)findViewById(R.id.JSONTextView);
textView.setText("Downloading JSON!");
new downloadJSON().execute("www.exampleURL.com/data1");
//new downloadJSON().execute(url2??);
}
private class downloadJSON extends AsyncTask<String, String, String>
{
protected String doInBackground(String... args) {
String result = "";
String formattedResult = "";
try {
InputStream stream = (InputStream)new URL(args[0]).getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
String line = "";
while (line != null) {
result += line;
line = reader.readLine();
}
JSONObject json = new JSONObject(result);
formattedResult = "Downloadable Puzzles\r\n--------------\r\n";
JSONArray puzzles = json.getJSONArray("PuzzleIndex");
for (int i = 0;i < puzzles.length(); ++i) {
formattedResult += puzzles.get(i) + "\r\n";
}
} catch (Exception e) {
e.printStackTrace();
}
return formattedResult;
}
protected void onPostExecute(String pResult) {
TextView textView = (TextView)findViewById(R.id.JSONTextView);
textView.setText(pResult);
}
}
Edit: my question is not a duplicate of the link posted below as my question has much more weight to it with the fact that JSON and URL's are involved. The link is in no way specific to my problem and doesn't help the question.
The Async task doesn't return the control to the calling method. It only runs the onPostExecute() in the main thread after completing the doInBackground() on a background thread.
One approach to transfer control back into calling method is to use interface.
public class DownloadJSON extends AsyncTask<String, String, String> {
private AsyncCallback mCallback;
public DownloadJSON(AsyncCallback callback) {
mCallback = callback;
}
protected String doInBackground(String... args) {
// process background task
}
protected void onPostExecute(String result) {
if (mCallback != null)
mCallback.onComplete(result);
}
public interface AsyncCallback {
void onComplete(String result);
}
}
And then start asynctask using
new DownloadJSON(new DownloadJSON.AsyncCallback() {
#Override
public void onComplete(String result) {
textView.setText(result);
}
}).execute("www.exampleURL.com/data1");
I can suggest you to abandon this old way of picking a thread from thread pool and execute this heavy operation at background thread
check out this awesome lib. RxJava

Using AsyncTask to login user

I need to get user and save it to variable.
public class MainActivity extends ActionBarActivity
{
User user = new LoginTask2().execute("");
}
class LoginTask2 extends AsyncTask<String, Void, User> {
private Exception exception;
public String hash = "";
protected String doInBackground(String... t) {
RestClient restClient = new HttpRestClient();
restClient.setUserAgent("bot/1.0 by name");
// Connect the user
User user = new User(restClient, "User", "somepass");
try {
user.connect();
//hash = user.getModhash();
return user;
} catch (Exception e) {
e.printStackTrace();
this.exception = e;
return null;
}
}
protected void onPostExecute(String string) {
}
}
It looks like it work, but I don't know how to get user. With this code I get error:
Error:(49, 47) error: incompatible types
required: String
found: AsyncTask<String,Void,String>
Could someone give me advice how to change code?
Your async task is declared:
class LoginTask2 extends AsyncTask<String, Void, User> {
protected String doInBackground(String... t) {
In order to avoid the incompatible types error, you need to make doInbackground return a User object.
protected User doInBackground(String... t) {
See: http://developer.android.com/reference/android/os/AsyncTask.html
The code you have above:
User user = new LoginTask2().execute("");
Will also fail because you must execute the async task and then later use the return value. You could access the returned User object by setting it as a field in your MainActivity and then using that object later once AsyncTask completes.
Define your asyntask as inner class and onPostExecute assign the mUser class variable.
public class MainActivity extends ActionBarActivity
{
User mUser;
new LoginTask2().execute("");
class LoginTask2 extends AsyncTask<String, Void, User> {
private Exception exception;
public String hash = "";
protected User doInBackground(String... t) {
RestClient restClient = new HttpRestClient();
restClient.setUserAgent("bot/1.0 by name");
// Connect the user
User user = new User(restClient, "User", "somepass");
try {
user.connect();
//hash = user.getModhash();
return user;
} catch (Exception e) {
e.printStackTrace();
this.exception = e;
return null;
}
}
protected void onPostExecute(User user) {
mUser = user;
}
}
}
The AsyncTask will not return the user variable when the execute method is called.
So this following code will not work.
User user = new LoginTask2().execute("");
Let's make a few changes.
private class LoginTask2 extends AsyncTask<String, Void, User> {
private Exception exception;
public String hash = "";
#Override
protected String doInBackground(String... t) {
RestClient restClient = new HttpRestClient();
restClient.setUserAgent("bot/1.0 by name");
// Connect the user
User user = new User(restClient, "User", "somepass");
try {
user.connect();
//hash = user.getModhash();
return user;
} catch (Exception e) {
e.printStackTrace();
this.exception = e;
return null;
}
}
protected void onPostExecute(User user) {
}
}
As your AsyncTask belongs only for your this class, you should let it private.
Also the return from the method doInBackground is the param from onPostExecute.
In order to save the user data you can take a few approaches:
One can use the onPostExecute method to save your data
protected void onPostExecute(User user) {
//do save stuff
}
You could also call an method from your class for example:
public class MainActivity extends ActionBarActivity {
User user = new LoginTask2().execute("");
private void success(User user){
//do save stuff
}
private void failure(){
}
private class LoginTask2 extends AsyncTask<String, Void, User> {
private Exception exception;
public String hash = "";
#Override
protected String doInBackground(String... t) {
RestClient restClient = new HttpRestClient();
restClient.setUserAgent("bot/1.0 by name");
// Connect the user
User user = new User(restClient, "User", "somepass");
try {
user.connect();
//hash = user.getModhash();
return user;
} catch (Exception e) {
e.printStackTrace();
this.exception = e;
return null;
}
}
protected void onPostExecute(User user) {
if(user != null)
success(user)
else
failure()
}
}
}
You can also catch an failure :)

Android AsyncTask in other class called from Activity

I have a MainActivity in which I instantiate a class. This class contains basic data and two important methods: GetRequestAccessUrl(params) and getToken(string) which returns an AuthResponse.
The first method runs fine, the string is generated and processed in the application. However, the getToken-method involves networking and is therefore prohibited to run on the main thread and AsyncTask is recommended. The implementation of the latter method is as following:
public AuthResponse getToken(String code) {
if (secrete == null) {
throw new IllegalStateException("Application secrete is not set");
}
try {
URI uri = new URI(TOKEN_URL);
URL url = uri.toURL();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
try {
StringBuilder sb = new StringBuilder();
sb.append("client_id=" + clientId);
sb.append("&client_secret=" + secrete);
sb.append("&code=" + code);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(sb.toString().getBytes("UTF-8"));
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
Reader br = new InputStreamReader((conn.getInputStream()));
Gson gson = new Gson();
return gson.fromJson(br, AuthResponse.class);
} finally {
conn.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
In the MainActivity the entire class is created, the first method is called, some actions are executed and the the getToken-method should run. However I seem to be completely stuck on how to do this, or how to create a (working) AsyncTask regarding this method. Any help is appreciated.
new YourAsyncTask ().execute(code);
private class YourAsyncTask extends AsyncTask<String, Integer, Integer> {
protected Long doInBackground(String... codes) {
AuthResponse res = getToken(codes[0]);
doSthWithRes(res);
}
protected void onProgressUpdate(Integer... progress) {}
protected void onPostExecute(Integer result) {}
}
This will probably work. Depending on what you wanna do with the AuthResponse.
As you can see the ASyncTask is more of a batch processing in the background. I prefer just using a Standard Thread. Additionally you may want to process the AuthResponse in the UIThread.
Here the Quick and dirty version:
/* It would be better to create a subclass of Runnable and pass the Code in the constructor*/
final String code = "testcode";
//Create the new Thread
Thread t = new Thread(new Runnable() {
#Override
public void run() {
final AuthResponse res = getToken(code);
//RunOnUiThread is a method of the Activity
runOnUiThread(new Runnable() {
#Override
public void run() {
doSomethingWithResponse(res);
}
});
}
});
t.start()
Try something like this
new AsyncTask<String, void, AuthResponse>() {
#Override
protected String doInBackground(String... params) {
String id = params[0];
String secret = params[1];
String code = params[2];
//do your stuff
return myAuthResponse;
}
#Override
protected void onPostExecute(AuthReponse result) {
//do stuff with AuthResponse
}
}.execute(clientId, clientSecret, code);
In onPostExecute you can handle the AuthResponse on the UIThread.
I think that I answered this in the following thread :
Java AsyncTask passing variable to main thread
A Http request is done in background in an Asyntask and the result is sent to the main activity thanks to a Callback. I gave a sample code on the answer.

Android Class with sub-class AsyncTask wait for the postExecute before returning the value

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.
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();
Implementing handler, and posting result back once result available.
Implementing observer design pattern, where you create an interface with methods such as 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();
}
}

Android Parse JSON stuck on get task

I am trying to parse some JSON data. My code was working for awhile, and I am not sure what I changed to suddenly break the code. When I run my code I am not receiving any runtime errors or warnings. I create a new AsyncTask and execute this. When I call .get() on this new task, the debugger stalls on this line and takes more than 30 minutes. I have not been able to get the debugger or during run to complete this task.
JSON:
protected void setUp(Context context) {
_context = context;
getConfig();
}
// get config file
protected void getConfig() {
if (config != null)
return;
config = new Config();
String url = configURL;
AsyncTask<String, Integer, JSONObject> jsonTask = new DownloadJSONTask()
.execute(url);
JSONObject configItem = null;
try {
configItem = jsonTask.get(); //debugger pauses here
if (configItem == null)
return;
config.configVersion = configItem.getString("field_configversion");
config.currentAppVersion = configItem
.getString("field_currentappversion");
config.getSupportURL = configItem.getString("field_getsupporturl");
config.getCatalogURL = configItem.getString("field_getcatalogurl");
config.getDataVersion = configItem.getString("field_dataversion");
config.getDataUrl = configItem.getString("field_dataurl");
config.getDataApiKey = configItem.getString("field_dataapikey");
} catch (InterruptedException e) {
e.printStackTrace();
System.err.println("Download of config interrupted");
} catch (ExecutionException e) {
e.printStackTrace();
System.err.println("Download of config failed to execute");
} catch (JSONException e) {
e.printStackTrace();
}
cacheStaticData(_context);
}
DownloadJSONTask.java
package com.example.simplegraph;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.os.AsyncTask;
public class DownloadJSONTask extends AsyncTask<String, Integer, JSONObject> {
private HttpClient client = new DefaultHttpClient();
private HttpGet request;
private HttpResponse response;
DownloadJSONTask() {
super();
}
// tries to grab the data for a JSONObject
#Override
protected JSONObject doInBackground(String... urls) {
request = new HttpGet(urls[0]);
try {
response = client.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String result = convertStreamToString(instream);
JSONObject json = new JSONObject(result);
instream.close();
return json;
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
// converts the InputStream to a string and add nl
private String convertStreamToString(InputStream is) {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
is.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
return sb.toString();
}
}
And HomeActivity.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
new AddStringTask().execute();
}
class AddStringTask extends AsyncTask<Void, String, Void> {
#Override
protected Void doInBackground(Void... unused) {
app = (EconApplication) getApplication();
getApp().setUp(HomeActivity.this);
HomeActivity.this.setUpDrawer();
return (null);
}
#Override
protected void onPostExecute(Void unused) {
setUpDataDisplay();
setUpGraphRange();
createTable();
createGraph(-1);
}
}
QUESTION: Why is my code getting stuck on .get()?
AsyncTask.get() blocks the caller thread. Use AsyncTask.execute() instead.
public final Result get ()
Added in API level 3
Waits if necessary for the computation to complete, and then retrieves
its result.
Returns The computed result.
Drawing from
How do I return a boolean from AsyncTask?
Try the below
new DownloadJSONTask(ActivityName.this).execute(url);
In your DownloadJSONTask
In the construcotr
TheInterface listener;
public DownloadJSONTask(Context context)
{
listener = (TheInterface) context;
}
Interface
public interface TheInterface {
public void theMethod(ArrayList<String> result); // your result type
}
In your doInbackground return the result. I am assuming its ArrayList of type String. Change the arraylist to what suits your requirement.
In your onPostExecute
if (listener != null)
{
listener.theMethod(result); // result is the ArrayList<String>
// result returned in doInbackground
// result of doInbackground computation is a parameter to onPostExecute
}
In your activity class implement the interface
public class ActivityName implements DownloadJSONTask.TheInterface
Then
#Override
public void theMethod(ArrayList<String> result) { // change the type of result according yo your requirement
// use the arraylist here
}
Edit: Alternative
You can makes your asynctask an inner class of your activity class. The result on doInbackground computation is a parameter to onPostExecute. Return result in doInbackground. Update ui in onPostExecute.
You can greatly simplify everything using the droidQuery library:
$.getJSON("http://www.example.com", null, new Function() {//this will run using an AsyncTask, get the JSON, and return either a JSONObject or JSONArray on the UI Thread.
#Overrde
public void invoke($ droidQuery, Object... params) {
if (params[0] instanceof JSONObject) { //it's often ok just to assume a JSONObject, making your first line simply: JSONObject obj = (JSONObject) params[0];
//JSONObject is returned
JSONObject json = (JSONObject) params[0];
//to easily parse this Object, convert it to a map first:
Map<String, ?> map = $.map(json);
//then you can just make a call like this:
if (map.contains("field_currentappversion")) {
config.currentAppVersion = (String) map.get("field_currentappversion");
}
}
else {
//JSONArray is returned
JSONArray json = (JSONArray) params[0];
//if you got an array, you can easily convert it to an Object[] for parsing:
Object[] array = $.makeArray(json);
}
}
});

Categories