doInBackground不更新变量

我正在开发一个基本的Android应用程序,它使用HttpURLConnection进行POST 。 我想从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 { 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; } } 

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

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

 class MyAwesomeAsyncTask extends AsyncTask { @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 { 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之前,您的活动/片段已经完成/完成,这可能会导致内存泄漏。

一个快速的谷歌搜索会告诉你有关AsyncTask泄漏内存的所有想法:)

您的doInBackground方法需要一些时间来执行。 你正在立即调用mTextView.setText(asyncExample.getResponseMsg());asynctask尚未完成。 您需要等到doInBackground完成后再调用setText您可以在onPostExecute方法中执行此onPostExecute

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

后执行:

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

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

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

有关更多信息,请参阅此处。

你可以通过多种方式实现这一目标。 我会尝试建议您对现有代码进行微不足道的更改。

将mTextView声明为全局变量,覆盖AsyncExample中的onPostExecute()方法,并使用doInBackground()方法传递给它的值更新onPostExecute()方法中的mTextView [注意,在doInBackground结束时返回responseMsg ()由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 { 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); } } 

试着这样做

主要活动

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