doInBackground不更新变量

时间:2017-11-30 14:06:48

标签: java android android-asynctask httpurlconnection

我正在开发一个基本的Android应用程序,使用POST HttpURLConnection。我想从Web API返回响应消息。

我的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());
    }
}

我的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;
    }
}

运行应用后,我在empty message中获得TextView。为什么我的doInBackground没有更新?即使con.getResponseMessage()null,也应该更新?

6 个答案:

答案 0 :(得分:2)

您的doInBackground方法需要一段时间才能执行。您立即致电mTextView.setText(asyncExample.getResponseMsg());,但asynctask尚未完成。您需要等到doInBackground完成后再调用setText,您可以使用onPostExecute方法执行此操作。

答案 1 :(得分:1)

AsyncTask有3种默认方法 1.在预执行 2.在后台做 3.在后执行

发布执行:

来自doinbackground的响应是在post执行中。 在这里我们可以处理结果。使用runnable方法更新文本视图ui

答案 2 :(得分:1)

重写onPostExecute()方法以返回文本。在主活动中创建一个方法,在完成异步任务的执行后更新TextView。它是空白的,因为Main Thread没有暂停执行并设置文本View但Async任务尚未完成执行,因此String为空。因此,在设置文本视图之前,请等待异步任务完成。

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

Refer to this for more information.

答案 3 :(得分:1)

问题是,当您尝试立即检索值时,异步执行AsyncTask。你需要以不同的方式实现这一点。要么利用AsyncTask的API,要么在UI线程上为你发布回调。您可以直接在TextView

中更新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);
    }
}

或者,如果您只想要该值,您可以将回调传递给异步任务,该任务将为您提供值,类似

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);
    }
}

以下是您创建它的方式

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

        }

        @Override
        public void onFailure() {

        }
    };

new MyAwesomeAsyncTask(callback).execute();

但是,要小心,因为如果由于某种原因你的活动/片段在AsyncTask完成之前消失/完成,这可能会导致内存泄漏。

快速Google搜索会告诉您关于AsyncTask泄漏内存的所有信息:)

答案 4 :(得分:0)

尝试这样做

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;
    }
}

答案 5 :(得分:0)

您可以通过多种方式完成此操作。我会尝试建议您对现有代码进行微不足道的更改。

将mTextView声明为全局变量,覆盖AsyncExample中的onPostExecute()方法,并使用doInBackground()方法传递给它的值更新onPostExecute()方法中的mTextView [注意,在此处返回responseMsg doInBackground()的结尾,由onPostExecute()方法作为String值(结果)捕获。但是,我也认为覆盖你的onPreExecute()方法是一个好主意。

为此,您的MainActivity.java应如下所示:

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();
    }
}

请将您的asynctask作为同一活动的内部类,并按如下方式进行编辑:

    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);
    }

}