Vinh Cong
Vinh Cong

Reputation: 23

HttpAsyncTask returns null as data

We have a problem getting HttpASyncTask to return a String from our simple http function: Simply we want to be able to send data to a URL and receive a proper response we can use later in our other classes. The httphandler class does receive the right response up until a point.

Here is our httphandler:

public class HttpRequester extends Activity {

static String result;

public String createUser(String username) {
    new HttpAsyncTask().execute("http://188.226.252.112/createPlayer.php?name=" + username);
    System.out.println("ID at createUser is; " + result); // this also returns null
    return result;
}

public static String GET(String url){
    InputStream inputStream = null;

    try {
        // create HttpClient
        HttpClient httpclient = new DefaultHttpClient();

        // make GET request to the given URL
        HttpResponse httpResponse = httpclient.execute(new HttpGet(url));

        // receive response as inputStream
        inputStream = httpResponse.getEntity().getContent();

        // convert inputstream to string
        if(inputStream != null)
            result = convertInputStreamToString(inputStream);
        else
            result = "Did not work!";

    } catch (Exception e) {
        Log.d("InputStream", e.getLocalizedMessage());
    }
    System.out.println("ID at GET is; " + result); // this returns correct ID
    return result;
}

private static String convertInputStreamToString(InputStream inputStream) throws IOException{
    StringBuilder sb = new StringBuilder();
    String something;
    BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
    while ((something = bufferedReader.readLine()) != null) {
        sb.append(something);
    }
    inputStream.close();
    result = sb.toString();
    System.out.println("ID at convert is; " + result); // this returns correct ID
    return result;

}

public boolean isConnected(){
    ConnectivityManager connMgr = (ConnectivityManager) getSystemService(this.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected())
        return true;
    else
        return false;
}

private class HttpAsyncTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
        return GET(urls[0]);
    }
}

}

And here is the other class' function which has to receive the data from the http handler:

HttpRequester requester = new HttpRequester();
ID = requester.createUser(login);
System.out.println("ID in other class is: " + ID); // this returns null

Please help

Regards

Cong Vinh

Upvotes: 2

Views: 180

Answers (1)

Kiril Aleksandrov
Kiril Aleksandrov

Reputation: 2591

Your approach is incorrect. When you call new HttpAsyncTask().execute() this starts a new asynchronous operation (a new thread is spawn under the hood). The execute method returns immediately and the result property stays null. This is why the createUser method returns null. The GET method is synchronous. In the context of your program it is executed in a separate thread (the thread started from the HttpAsyncTask) but all methods in it are executed consistently. This is why the result property here is initialized and holds the correct result.

  • It is not a good practice to have shared property (the result property) between different threads. This can be the root of serious concurrent problems. The better approach is to keep this property part of the HttpAsyncTask class and return it as a result of the AsyncTask execution.
  • Do the processing of the result in the postExecuted method of the HttpAsyncTask class (that is not implemented here but can be overridden). This is the only correct way that you can be sure that the processing will be executed after the HTTP call has been made and the result has been received.

Upvotes: 2

Related Questions