Android is returning a String after 'AsyncTask'

384 Views Asked by At

Here is my code:

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.os.AsyncTask;
import android.util.Log;

public class JsonController 
{
    private JSONObject inputData, json, finalResult;
    private String authentication;

    public JsonController()
    {
        json = new JSONObject();

        inputData = new JSONObject();
    }

    public void createAuthentication(String userName, String apiKey)
    {
        authentication = "";
    }


    public void setModel(String model) throws JSONException
    {
        json.put("model",model);
    }

    public void setData(String id, String deviceType) throws JSONException
    {
        inputData.put(id, deviceType);
    }



    public void getPrediction()
    {
        new sendJSon().execute("");
            return finalResult.toString();
    }




    private class sendJSon extends AsyncTask<String,Void,String>
    {

        @Override
        protected String doInBackground(String... params) {
            // TODO Auto-generated method stub
            HttpClient httpclient = new DefaultHttpClient();

            HttpPost httppost = new HttpPost(authentication);
            httppost.setHeader("Content-type", "application/json; charset=utf-8");

            try {
                  // Add your data
                  json.put("input_data", inputData);

                  StringEntity se = new StringEntity( json.toString());
                  httppost.setEntity(se); 

                  // Execute HTTP Post Request
                  HttpResponse response = httpclient.execute(httppost);

                  BufferedReader reader = new BufferedReader(
                          new InputStreamReader(
                                  response.getEntity().getContent(), "UTF-8"));
                  String jsonString = reader.readLine();
                  JSONTokener tokener = new JSONTokener(jsonString);

                  finalResult = new JSONObject(tokener);
              }
              catch(Exception e)
              {
                  Log.d("Error here", "Error is here",e);
              }


            return null;
        }

    }
}

This code always crashes in getPrediction() because of NulPointerException. NullPointerException is because the Async task take time to generate the String, and the getPrediction() method returns the string before it is ready. All of these methods get called via external classes, so how can I solve this?

5

There are 5 best solutions below

0
On

you can check whether ASYNCTASK has finished execution or not until then you can halt the returning of string from method getPrediction();

if(CLASSOBJECT!= null && CLASSOBJECT.getStatus() == Status.RUNNING) {
            //DO NOT RETURN ANY VALUE
        }else{
//RETURN VALUE
}
0
On

Try to return the String in your doInBackground method as :

  return jsonString;
0
On

As you have pointed

outNullPointerException is because the Async task take time to generate the
String, and the getPrediction() method returns the string before it is ready.

You should run your network based operation in thread in doInBackground and then join that thread. Then you should call getPrediction() in onPostExecute(). Thus you'll have the data before the method is called.

0
On

Use onPostExecute() instead. onPostExecute() receives the return value from doInBackground() after it finishes. From there you can do whatever needs to be done with your result.

If onPostExecute() isn't flexible enough for you, consider using a CountDownLatch to stall your main code execution until AsyncTask returns.

0
On

Here is an sample code which you can implement

public interface AsyncResponseHandler {
    public String resultCall(String resultStr);
}

public class MyMainClass extends Activity implements AsyncResponseHandler{

    public void doProcessing(){
        new AsynTasker(this).execute(null); //here this is instance of AsyncResponseHandler
    }

    @Override
    public String resultCall(String resultStr) {
        //here you will receive results from your async task after execution and you can carry out whatever process you want to do.
    }
}

public class AsynTasker extends AsyncTask<String,Void,String>{
    AsyncResponseHandler handler=null;
    public AsynTasker(AsyncResponseHandler handler){
      this.handler = handler
    }

    @Override
    protected String doInBackground(String... params) {
         // do your processing
         return resultString;
    }

    @Override
    protected void onPostExecute(String result) {
        this.handler.resultCall(result);
    }

}