androidandroid-asynctaskinner-classesouter-classes

Access private variable from inner class (AsyncTask)


I have a problem, I am trying to access a private variable of an outer class from a doInBackground method of an AsyncTask which is the inner class. Here there is the full code.

public class MessageHandler {
private Contact receiver;
private String senderFacebookId;
private String message;
private final String TAG = "MessageHandler";
private Context context;
boolean sentResult;

public MessageHandler(Contact receiver, String senderFacebookId, String message, Context context) {
    this.receiver = receiver;
    this.senderFacebookId = senderFacebookId;
    this.message = message;
    this.context=context;
    this.sentResult = false;
}

public void send(){
    Log.i(TAG, "Sending message to " + receiver.getName() + " receiver id: " + receiver.getFacebook_id() + " sender id: " + senderFacebookId + " message: " + message);

    new SenderAsync().execute(senderFacebookId,message, receiver.getFacebook_id());
    if(this.sentResult==true){
        Toast toast = Toast.makeText(this.context, "Message Sent", Toast.LENGTH_LONG);
        toast.show();

    }else{
        Toast toast = Toast.makeText(this.context, "ERROR: Message not Sent", Toast.LENGTH_LONG);
        toast.show();
    }
}



private class SenderAsync extends AsyncTask<String,String,String> {

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }

    @Override
    protected String doInBackground(String... params) {
        HttpClient client = new DefaultHttpClient();

        try {
            List<NameValuePair> parameter = new ArrayList<>(1);
            parameter.add(new BasicNameValuePair("regId", "empty"));
            parameter.add(new BasicNameValuePair("sender_id", params[0]));
            parameter.add(new BasicNameValuePair("receiver_facebook_id", params[2]));

            parameter.add(new BasicNameValuePair("message", params[1]));

            String paramString = URLEncodedUtils.format(parameter, "utf-8");
            HttpGet get = new HttpGet(ProfileFragment.SERVER_URL_SEND_MESSAGE+"?"+paramString);

            Log.i(TAG, paramString);
            HttpResponse resp = client.execute(get);
            System.out.println("SREVER RESPONSE " + resp.getStatusLine().getStatusCode());

            //THIS IS THE VARIABLE THAT I WANT TO ACCESS
            if(resp.getStatusLine().getStatusCode()==200){
                MessageHandler.this.sentResult = true;
            }



        } catch (IOException e) {

            Log.i(TAG,"Error :" + e.getMessage());
        }
        return null;
    }
}

}

The variable that I am trying to access is the boolean variable sentResult. I also print out the response of the server which is always 200. Even if I remove the if condition and I set it to be true in any case, it looks like that that line of code is never executed and the variable not accessed, so it is always false.


Solution

  • The entire point of an async task is that it is asynchronous. If you execute a task, you will not get the results back on your next line of code. In order to evaluate the result, you should be using the onPostExecute callback method.

    @Override
    protected void onPostExecute(String s) {
        if(sentResult==true){
            Toast toast = Toast.makeText(this.context, "Message Sent", Toast.LENGTH_LONG);
            toast.show();
        }else{
            Toast toast = Toast.makeText(this.context, "ERROR: Message not Sent", Toast.LENGTH_LONG);
            toast.show();
        }
    }
    

    Also, if you were to change your method signatures, you wouldn't even need an external variable.

    private class SenderAsync extends AsyncTask<String,String,Boolean> {
    

    @Override
    protected void onPostExecute(Boolean sent) {
        if(sent == true){
            Toast toast = Toast.makeText(this.context, "Message Sent", Toast.LENGTH_LONG);
            toast.show();
        }else{
            Toast toast = Toast.makeText(this.context, "ERROR: Message not Sent", Toast.LENGTH_LONG);
            toast.show();
        }
    }
    
    @Override
    protected Boolean doInBackground(String... params) {
        try {
            ...
            if (resp.getStatusLine().getStatusCode() == 200) {
                return true;
            }
        }
        catch (IOException e) {
    
        }
    
        return false;
    }