对于我的项目,我需要检查一个URL以查看它是否存在。
所以我创建了一个HttpURLConnection
并连接到url并等待响应代码。
由于我无法在主线程中使用该HttpURLConnection,因此我必须将其移至AsyncTask并让它在单独的线程上运行。
这就是我的AsyncTask代码(只有重要的部分):
private class URLExists extends AsyncTask<String, Void, Boolean> {
protected Boolean doInBackground(String... urls)
{
boolean isValid = false;
try
{
URL myurl = new URL(urls[0]);
HttpURLConnection.setFollowRedirects(false);
HttpURLConnection connection = (HttpURLConnection) myurl.openConnection();
connection.setUseCaches(true);
connection.setRequestMethod("HEAD");
connection.connect();
int code = connection.getResponseCode();
...
connection.disconnect();
if(code != 404)
isValid = true;
else
isValid = false;
}
...
return isValid;
}
protected void onPostExecute(Boolean isValid)
{
isTrue = isValid;
}
}
所以基本上我得到一个布尔值isTrue
,它告诉我url是否有效。当我运行这个时,我得到了正确的结果,一切正常。
但是现在,当我执行这个AsyncTask时,它显然与我的主线程并行运行。
我有这段代码:
new URLExists().execute("https://www.example.com");
if(isTrue)
{
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Do Something
}
});
}
由于我的AsyncTask并行运行,我的主线程执行下一个操作而不等待AsyncTask的结果。由于isTrue
默认为false
,因此if语句永远不会运行。
当然我知道AsyncTask中的protected void onPostExecute()
,但这是否意味着我的主线程中的所有代码必须在并行线程中的该函数中?这一切都取决于URL检查的结果。
我知道.get()方法,但这冻结了我的MainThread和UI,所以对我来说这不是一个真正的选择。
还有其他方法让主线程等待AsyncTask吗?我知道失败了AsyncTask的目的,但我想要的只是检查URL是否存在而且我只能在AsyncTask中进行检查。
答案 0 :(得分:0)
您的任务不需要多线程。您需要的只是检查网址是否可用。对?当然可能需要一些时间,你必须在主线程中等待这段时间。那就对了。但是你还需要等待。不要造成不必要的复杂性。只需阅读网址,获取响应代码,验证它,检查超时异常,你就可以了。
答案 1 :(得分:0)
我们需要查看AsyncTask的规范。通常在任何异步方法中,您都有一个回调函数,可以让您知道后台操作已完成。对于Android,它是onPostExecute()
可以在这里找到。 http://developer.android.com/reference/android/os/AsyncTask.html
执行异步任务时,任务将经历4个步骤:
onPreExecute()
,在执行任务之前在UI线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。
doInBackground(Params...)
,在onPreExecute()完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数将传递给此步骤。计算结果必须由此步骤返回,并将传递回最后一步。此步骤还可以使用publishProgress(Progress ...)发布一个或多个进度单元。这些值发布在UI线程的onProgressUpdate(Progress ...)步骤中。
onProgressUpdate(Progress...)
,在调用publishProgress(Progress ...)后在UI线程上调用。执行的时间是不确定的。此方法用于在后台计算仍在执行时显示用户界面中的任何形式的进度。例如,它可用于为进度条设置动画或在文本字段中显示日志。
onPostExecute(Result)
,在后台计算完成后在UI线程上调用。后台计算的结果作为参数传递给此步骤。
对于您的具体情况,您可能想要做这样的事情......
yourAsyncTask{
@Override
protected Boolean doInBackground(Void... params){
// CHECK YOUR URL HERE
}
.
.
.
@Override
public void onPostExecute(Result result){
if(isTrue) {
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Do Something
}
});
}
}
}