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