我正在开发一个基本的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
,也应该更新?
答案 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();
答案 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);
}
}