我正在阅读AsyncTask,我尝试了下面的简单程序。但这似乎不起作用。我怎样才能让它工作?
AsyncTask
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>
好的,您正在尝试通过另一个线程访问 GUI。总的来说,这不是好的做法。
AsyncTask 在doInBackground()另一个线程内执行所有内容,该线程无权访问您的视图所在的 GUI。
doInBackground()
preExecute()并postExecute()在此新线程中发生繁重工作之前和之后为您提供对 GUI 的访问,您甚至可以将长时间操作的结果传递postExecute()给然后显示任何处理结果。
preExecute()
postExecute()
请参阅稍后更新 TextView 的这些行:
TextView txt = findViewById(R.id.output); txt.setText("Executed");
把它们放进去onPostExecute()。
onPostExecute()
然后,您将看到doInBackground完成后更新的 TextView 文本。
doInBackground
我注意到您的 onClick 侦听器不会检查已选择的视图。我发现最简单的方法是通过 switch 语句。我在下面编辑了一个完整的课程,其中包含所有避免混淆的建议。
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 implements OnClickListener { Button btn; AsyncTask<?, ?, ?> runningTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = findViewById(R.id.button1); // Because we implement OnClickListener, we only // have to pass "this" (much easier) btn.setOnClickListener(this); } @Override public void onClick(View view) { // Detect the view that was "clicked" switch (view.getId()) { case R.id.button1: if (runningTask != null) runningTask.cancel(true); runningTask = new LongOperation(); runningTask.execute(); break; } } @Override protected void onDestroy() { super.onDestroy(); // Cancel running task(s) to avoid memory leaks if (runningTask != null) runningTask.cancel(true); } private final class LongOperation extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { // We were cancelled; stop sleeping! } } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); // txt.setText(result); // You might want to change "executed" for the returned string // passed into onPostExecute(), but that is up to you } } }