doInBackground not updating variable

人走茶凉 提交于 2019-12-23 06:16:23

问题


I'm working on a basic android app that makes a POST with HttpURLConnection. I want to return the response Message from my Web API.

My MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final TextView mTextView = findViewById(R.id.textView);
        AsyncExample asyncExample = new AsyncExample();
        asyncExample.execute();
        mTextView.setText(asyncExample.getResponseMsg());
    }
}

My AsyncExample.java

class AsyncExample extends AsyncTask<Void, Void, Void> {
    private HttpURLConnection con;
    private String responseMsg;

    protected void onPreExecute() {
        responseMsg = "empty message";
    }

    @Override
    protected Void doInBackground(Void... params) {
        String urlParameters = "param1=data1";

        byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
        int postDataLength = postData.length;
        String request = "http://192.168.1.30:6262";
        URL url = null;
        try {
            url = new URL(request);
            con = (HttpURLConnection) url.openConnection();
            con.setDoOutput(true);
            con.setInstanceFollowRedirects(false);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("charset", "utf-8");
            con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
            responseMsg = con.getResponseMessage();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getResponseMsg() {
        return responseMsg;
    }
}

After running the app, i get empty message in my TextView. Why it is not getting updated my doInBackground? Even if con.getResponseMessage() is null, it should be updated?


回答1:


The problem is that your AsyncTask is executed asynchronously, while you try to retrieve the value immediately. You need to implement this a little bit differently. Either leverage the API of AsyncTask, sine it posts callbacks for your on the UI thread. You can update your TextView directly in your AsyncTask

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {

    @Override
    protected void onPreExecute() {
        myTextView.setText("progress started");
    }

    @Override
    protected String doInBackground(final Void... voids) {
        String s = amazingCallToBackend();
        return s;
    }

    @Override
    protected void onPostExecute(final String s) {
        myTextView.setText(s);
    }
}

Or if you just want the value, you can pass a Callback to your async task that will deliver the value to you, something like that

interface Callback {
    void onValueReceived(String value);
    void onFailure();
}

class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {

    private Callback callback;

    MyAwesomeAsyncTask(final Callback callback) {
        this.callback = callback;
    }

    @Override
    protected String doInBackground(final Void... voids) {
        String s = amazingCallToBackend();
        return s;
    }

    @Override
    protected void onPostExecute(final String s) {
        callback.onValueReceived(s);
    }
}

Here's how you create it

Callback callback = new Callback() {
        @Override
        public void onValueReceived(final String value) {

        }

        @Override
        public void onFailure() {

        }
    };

new MyAwesomeAsyncTask(callback).execute();

However, be careful because if for some reason your activity/fragment is gone/finished before your AsyncTask is done, this can cause memory leaks.

A quick Google search will tell you all you want about AsyncTask leaking memory :)




回答2:


Your doInBackground method take time to execute. you are immediately calling mTextView.setText(asyncExample.getResponseMsg()); but asynctask has been not been finished yet. You need to wait until your doInBackground finish and then call that setText you can do it in onPostExecute method.




回答3:


AsyncTask has 3 default method 1. On preexecute 2. Do in background 3. On post execute

post execute:

The response got from the doinbackground is in the post execute. Here we can process the result . use the runnable method to update text view ui




回答4:


Override the onPostExecute() Method to return the text. In the Main Activity create a method to update the TextView after completing the execution of the Async Task. It is coming blank as because the Main Thread is not paused its executing and setting the text View but the Async task has not yet finished executing and hence the String is empty. So wait for the Async Task to finish before setting the text view.

String str_result= new RunInBackGround().execute().get();

Refer to this for more information.




回答5:


You can do it in a number of ways. I'd try to suggest you a way that would require negligible amount of changes to your existing code.

Declare the mTextView as a Global variable, Override onPostExecute() method inside your AsyncExample and update mTextView inside that onPostExecute() method with the value passed to it by the doInBackground() method [here, notice that responseMsg is returned at the end of doInBackground() ground which is caught as a String value (result) by the onPostExecute() method]. However, I also think that its a good idea to Override your onPreExecute() method.

In order to do so, your MainActivity.java should be as follows:

public class MainActivity extends AppCompatActivity {
TextView mTextView;    //declare mTextView outside the onCreate() method as a Global String variable.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.textView);
        AsyncExample asyncExample = new AsyncExample();
        asyncExample.execute();
    }
}

Please make your asynctask an inner-class of the same activity and edit it as follows:

    class AsyncExample extends AsyncTask<Void, Void, Void> {
    private HttpURLConnection con;
    private String responseMsg;

    @Override           // Its a good practice to Override the onPreExecute() method.
    protected void onPreExecute() {
        responseMsg = "empty message";
    }

    @Override
    protected String doInBackground(String... params) {
        String urlParameters = "param1=data1";

        byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
        int postDataLength = postData.length;
        String request = "http://192.168.1.30:6262";
        URL url = null;
        try {
            url = new URL(request);
            con = (HttpURLConnection) url.openConnection();
            con.setDoOutput(true);
            con.setInstanceFollowRedirects(false);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("charset", "utf-8");
            con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
            responseMsg = con.getResponseMessage();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return responseMsg;    //return the value of responseMsg
    }

        @Override      //override onPostExecute() method
        protected void onPostExecute(String result) {    //receive the value to be set to mTextView which is returned by the doInBackground() method.
           mTextView.setText(result);
    }

}



回答6:


Try to do like this

MainActivity

public class MainActivity extends AppCompatActivity {
TextView mTextView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = findViewById(R.id.textView);
    AsyncExample asyncExample = new AsyncExample(this,mTextView);
    asyncExample.execute();
  }
}

AsyncTask

    class AsyncExample extends AsyncTask<Void, Void, Void> {
    private HttpURLConnection con;
    private String responseMsg;
    private MainActivity mContext;
    TextView mTextView;

    public AsyncExample (MainActivity context, TextView textView) {
        mContext = context;
        mTextView = textView;
    } 

    protected void onPreExecute() {
        responseMsg = "empty message";
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected Void doInBackground(Void... params) {
        String urlParameters = "param1=data1";

        byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
        int postDataLength = postData.length;
        String request = "http://192.168.1.30:6262";
        URL url = null;
        try {
            url = new URL(request);
            con = (HttpURLConnection) url.openConnection();
            con.setDoOutput(true);
            con.setInstanceFollowRedirects(false);
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("charset", "utf-8");
            con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
            responseMsg = con.getResponseMessage();
            mContext.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mTextView.setText(responseMsg);
                }
            });
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String getResponseMsg() {
        return responseMsg;
    }
}


来源:https://stackoverflow.com/questions/47575399/doinbackground-not-updating-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!