我正在阅读 AsyncTask
,我尝试了下面的简单程序 . 但它似乎没有用 . 我怎样才能使它工作?
package com.test;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class AsyncTaskActivity extends Activity {
Button btn;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener((OnClickListener) this);
}
public void onClick(View view){
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
return null;
}
@Override
protected void onPostExecute(String result) {
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
}
我只是想在后台进程中在5秒后更改标签 .
这是我的 main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="false"
android:max="10"
android:padding="10dip">
</ProgressBar>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Progress" >
</Button>
<TextView android:id="@+id/output"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Replace"/>
</LinearLayout>
16 回答
背景/理论
AsyncTask 允许您在后台线程上运行任务,同时将结果发布到UI线程 .
实施
AsyncTask 是一个通用类 . (它的构造函数需要 parameterized types . )
它使用这些 three generic types:
Params - 执行时发送给任务的参数类型 .
Progress - 后台计算期间发布的进度单元的类型 .
Result - 后台计算结果的类型 .
您可以在 AsyncTask 中覆盖这三个参数 correspond to three primary functions :
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
To execute AsyncTask
调用 execute() 并将参数发送到后台任务 .
What Happens
在main / UI线程上,调用 onPreExecute() . (初始化此线程中的某些内容,例如在用户界面上显示进度条 . )
在后台线程上,调用 doInBackground(Params...) . (参数是传递给Execute函数的参数 . )
应该发生长时间运行的任务
必须至少覆盖
doInBackground()
才能使用AsyncTask .调用 publishProgress(Progress...) 以在后台计算仍在执行时更新用户界面中的进度显示 . (例如,为进度条设置动画或在文本字段中显示日志 . )
这会导致 onProgressUpdate() 被调用 .
在后台线程上,从
doInBackground()
返回结果 . 这会触发下一步 .在main / UI线程上,使用返回的结果调用 onPostExecute() .
例子
再次使用阻止任务的示例是从Web下载内容,
Example A downloads an image 并将其显示在ImageView中,
而 Example B downloads some files .
示例A.
doInBackground()
方法下载图像并将其存储在BitMap类型的对象中 .onPostExecute()
方法获取位图并将其放在ImageView中 .例B
Example B execution
当您在工作线程中时,您无法直接操作Android上的UI元素 .
当您使用AsyncTask时,请了解回调方法 .
例如:
仅供参考:要从工作线程访问UI线程,可以在视图上使用runOnUiThread()方法或post方法 .
例如:
这将有助于您更好地了解事情 . 因此,在您的情况下,您需要在onPostExecute()方法中设置textview .
带POST请求的示例异步任务:
我的完整答案是here,但这是一个解释性图片,以补充本页面上的其他答案 . 对我来说,了解所有变量的去向是开始时最令人困惑的部分 .
执行异步任务时,任务将执行4个步骤:
onPreExecute()
doInBackground(Params ...)
onProgressUpdate(进度......)
onPostExecute(结果)
以下是演示示例
一旦你创建了,任务就会非常简单地执行:
我希望这能帮到您...
移动这两行:
超出你的AsyncTask的
doInBackground
方法并将它们放在onPostExecute
方法中 . 你的AsyncTask
应该是这样的:好的,你试图通过另一个线程访问GUI . 这主要是不好的做法 .
AsyncTask执行另一个线程中
doInBackground()
内的所有内容,该线程无法访问您的视图所在的GUI .preExecute()
和postExecute()
为您提供在此新线程中发生繁重操作之前和之后的GUI访问权限,您甚至可以将长操作的结果传递给postExecute()
,然后显示任何处理结果 .请参阅稍后更新TextView的这些行:
把它们放在
PostExecute()
然后,在
doInBackground
完成后,您将看到TextView文本已更新 .EDIT: 我注意到你的onClick监听器没有检查是否已经选择了哪个View . 我发现最简单的方法是通过switch语句 . 我在下面编辑了一个完整的课程,提出了所有建议以避免混淆 .
我确定它正在执行,但您正在尝试更改UI元素在后台线程中,这是不会做的 .
按如下方式修改您的调用和AsyncTask:
Calling Class
Note: 我个人建议在执行AsyncTask线程的地方使用
onPostExecute()
,而不是在扩展AsyncTask本身的类中 . 我认为它使代码更容易阅读,特别是如果您需要在多个地方处理结果略有不同的AsyncTask .LongThread class (extends AsyncTask):
只是:
你需要声明按钮onclicklistener,一旦点击它调用AsyncTask类的DownloadJson,过程将如下所示:
我创建了一个使用Android的AsyncTask的简单示例 . 它以
onPreExecute(), doInBackground(), publishProgress()
开头,最后是onProgressUpdate()
.在这个doInBackground()作为后台线程,而其他工作在UI线程 . 您无法访问doInBackground()中的UI元素 . 序列与我提到的相同 .
但是,如果您需要从
doInBackground
更新任何小部件,您可以publishProgress
从doInBackground
调用onProgressUpdate
来更新您的UI小部件 .在您的活动中将其称为:
Developer Reference Here
更改您的代码,如下所示:
我建议您使用此库进行背景设计,让您的生活更轻松https://github.com/Arasthel/AsyncJobLibrary
它这么简单..
以异步方式执行操作的最短示例:
要运行它:
Sample AsyncTask example with progress