doInBackground 不更新变量
doInBackground not updating variable
我正在开发一个基本的 android 应用程序,它使 POST
具有 HttpURLConnection
。我想 return 来自我的网站的响应消息 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;
}
}
在 运行 应用程序之后,我在 TextView
中得到 empty message
。为什么它没有更新我的 doInBackground
?即使con.getResponseMessage()
是null
,也要更新吗?
尝试这样做
主要活动
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();
}
}
异步任务
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;
}
}
AsyncTask 有 3 个默认方法
1. 预执行
2.在后台做
3. 在 post 执行
post执行:
从 doinbackground 得到的响应在 post 执行中。
在这里我们可以处理结果。使用 runnable 方法更新文本视图 ui
将 onPostExecute()
方法重写为 return 文本。在 Main Activity 中创建一个方法来在完成异步任务的执行后更新 TextView。它变为空白,因为 Main Thread
没有暂停其执行和设置文本视图,但异步任务尚未完成执行,因此字符串为空。所以在设置文本视图之前等待异步任务完成。
String str_result= new RunInBackGround().execute().get();
Refer to this for more information.
您的 doInBackground 方法需要时间来执行。您正在立即呼叫 mTextView.setText(asyncExample.getResponseMsg());
但 asynctask
尚未完成。你需要等到你的 doInBackground 完成然后调用 setText
你可以在 onPostExecute
方法中完成。
您可以通过多种方式进行。我会尝试向您推荐一种方法,该方法只需对现有代码进行微不足道的更改。
将 mTextView 声明为全局变量,覆盖 AsyncExample 中的 onPostExecute() 方法,并使用 doInBackground() 方法传递给它的值更新 onPostExecute() 方法中的 mTextView [此处,注意返回了 responseMsg在 doInBackground() 地面的末尾,它被 onPostExecute() 方法捕获为字符串值(结果)]。但是,我也认为重写您的 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 设为相同 activity 的 inner-class 并按如下方式编辑:
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);
}
}
问题是您的 AsyncTask
是异步执行的,而您试图立即检索值。您需要稍微不同地实现它。要么利用 AsyncTask 的 API,因为它会在 UI 线程上为您发布回调。您可以直接在 AsyncTask
中更新 TextView
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();
但是,要小心,因为如果由于某种原因你的 activity/fragment 在你的 AsyncTask 完成之前是 gone/finished,这可能会导致内存泄漏。
快速 Google 搜索将告诉您有关 AsyncTask 内存泄漏的所有信息:)
我正在开发一个基本的 android 应用程序,它使 POST
具有 HttpURLConnection
。我想 return 来自我的网站的响应消息 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;
}
}
在 运行 应用程序之后,我在 TextView
中得到 empty message
。为什么它没有更新我的 doInBackground
?即使con.getResponseMessage()
是null
,也要更新吗?
尝试这样做
主要活动
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();
}
}
异步任务
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;
}
}
AsyncTask 有 3 个默认方法 1. 预执行 2.在后台做 3. 在 post 执行
post执行:
从 doinbackground 得到的响应在 post 执行中。 在这里我们可以处理结果。使用 runnable 方法更新文本视图 ui
将 onPostExecute()
方法重写为 return 文本。在 Main Activity 中创建一个方法来在完成异步任务的执行后更新 TextView。它变为空白,因为 Main Thread
没有暂停其执行和设置文本视图,但异步任务尚未完成执行,因此字符串为空。所以在设置文本视图之前等待异步任务完成。
String str_result= new RunInBackGround().execute().get();
Refer to this for more information.
您的 doInBackground 方法需要时间来执行。您正在立即呼叫 mTextView.setText(asyncExample.getResponseMsg());
但 asynctask
尚未完成。你需要等到你的 doInBackground 完成然后调用 setText
你可以在 onPostExecute
方法中完成。
您可以通过多种方式进行。我会尝试向您推荐一种方法,该方法只需对现有代码进行微不足道的更改。
将 mTextView 声明为全局变量,覆盖 AsyncExample 中的 onPostExecute() 方法,并使用 doInBackground() 方法传递给它的值更新 onPostExecute() 方法中的 mTextView [此处,注意返回了 responseMsg在 doInBackground() 地面的末尾,它被 onPostExecute() 方法捕获为字符串值(结果)]。但是,我也认为重写您的 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 设为相同 activity 的 inner-class 并按如下方式编辑:
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);
}
}
问题是您的 AsyncTask
是异步执行的,而您试图立即检索值。您需要稍微不同地实现它。要么利用 AsyncTask 的 API,因为它会在 UI 线程上为您发布回调。您可以直接在 AsyncTask
TextView
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();
但是,要小心,因为如果由于某种原因你的 activity/fragment 在你的 AsyncTask 完成之前是 gone/finished,这可能会导致内存泄漏。
快速 Google 搜索将告诉您有关 AsyncTask 内存泄漏的所有信息:)