AsyncTask的Android例子

我正在阅读关于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> 

好的,你正试图通过另一个线程访问GUI。 这主要是不好的做法。

AsyncTask执行另一个线程内的doInBackground()所有内容,该线程无法访问视图所在的GUI。

preExecute()postExecute()为您提供在这个新线程繁重的前​​后对GUI的访问,甚至可以将长操作的结果传递给postExecute() ,然后显示任何处理结果。

看到以后更新TextView的位置:

 TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); 

把它们放在PostExecute()

doInBackground完成之后,您将看到更新的TextView文本。

编辑:我注意到你的onClick监听器不检查看哪个视图已被选中。 我发现最简单的方法是通过switch语句。 我有一个完整的课程编辑下面的所有build议,以避免混淆。

 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; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); // because we implement OnClickListener we only have to pass "this" // (much easier) btn.setOnClickListener(this); } public void onClick(View view) { // detect the view that was "clicked" switch (view.getId()) { case R.id.button1: new LongOperation().execute(""); break; } } 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) { Thread.interrupted(); } } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); // txt.setText(result); // might want to change "executed" for the returned string passed // into onPostExecute() but that is upto you } @Override protected void onPreExecute() {} @Override protected void onProgressUpdate(Void... values) {} } } 

我的完整答案在这里 ,但这里是一个解释性的图像,以补充在这个页面上的其他答案。 对于我来说,了解所有variables发生的地方是开始时最混乱的部分。

在这里输入图像描述

我确定它正在正确执行,但是您正在尝试更改后台线程中的UI元素,而这样做不会。

修改你的电话和AsyncTask如下:

调用类

注:我个人build议使用onPostExecute()无论你执行AsyncTask线程,而不是在扩展AsyncTask本身的类。 我认为它使得代码更容易阅读,特别是如果你需要在多个地方处理结果略有不同的AsyncTask。

 new LongThread() { @Override public void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText(result); } }.execute(""); 

LongThread类(扩展AsyncTask):

 @Override protected String doInBackground(String... params) { for(int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } return "Executed"; } 

概念和代码在这里

我已经创build了一个简单的例子来使用Android的AsyncTask。 它从onPreExecute(), doInBackground(), publishProgress()onProgressUpdate()

在这个doInBackground()工作作为后台线程,而其他工作在UI线程。 您无法访问doInBackground()中的UI元素。 序列和我所提到的一样。

但是,如果您需要从doInBackground更新任何窗口小部件, doInBackground可以从doInBackground一个将会调用onProgressUpdate来更新UI窗口小部件的doInBackground

 class TestAsync extends AsyncTask<Void, Integer, String> { String TAG = getClass().getSimpleName(); protected void onPreExecute (){ super.onPreExecute(); Log.d(TAG + " PreExceute","On pre Exceute......"); } protected String doInBackground(Void...arg0) { Log.d(TAG + " DoINBackGround","On doInBackground..."); for(int i=0; i<10; i++){ Integer in = new Integer(i); publishProgress(i); } return "You are at PostExecute"; } protected void onProgressUpdate(Integer...a){ super.onProgressUpdate(a); Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]); } protected void onPostExecute(String result) { super.onPostExecute(result); Log.d(TAG + " onPostExecute", "" + result); } } 

在你的活动中像这样称呼它:

 new TestAsync().execute(); 

开发者参考这里

移动这两行:

 TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); 

在你的AsyncTask的doInBackground方法中,并把它们放在onPostExecute方法中。 你的AsyncTask应该是这样的:

 private class LongOperation extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { try { Thread.sleep(5000); // no need for a loop } catch (InterruptedException e) { Log.e("LongOperation", "Interrupted", e); return "Interrupted"; } return "Executed"; } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.output); txt.setText(result); } } 

最简单的例子,只是做asynchronous的东西:

 class MyAsyncTask extends android.os.AsyncTask { @Override protected Object doInBackground(Object[] objects) { //do something asynchronously return null; } } 

运行它:

 (new MyAsyncTask()).execute(); 

当一个asynchronous任务被执行时,任务要经过4个步骤:

  1. onPreExecute()
  2. doInBackground(参数…)
  3. onProgressUpdate(进展…)
  4. onPostExecute(结果)

下面是一个演示例子

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } 

一旦你创build,一个任务很简单:

  new DownloadFilesTask().execute(url1, url2, url3); 

我希望这会帮助你…

当您在工作线程中时,无法直接操作Android上的UI元素。

当你使用AsyncTask时,请理解callback方法。

例如:

 public class MyAyncTask extends AsyncTask<Void, Void, Void>{ @Override protected void onPreExecute() { // Here you can show progress bar or something on the similar lines. // Since you are in a UI thread here. super.onPreExecute(); } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); // After completing execution of given task, control will return here. // Hence if you want to populate UI elements with fetched data, do it here. } @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); // You can track you progress update here } @Override protected Void doInBackground(Void... params) { // Here you are in the worker thread and you are not allowed to access UI thread from here. // Here you can perform network operations or any heavy operations you want. return null; } } 

仅供参考:要从工作线程访问UI线程,请在视图上使用runOnUiThread()方法或post方法。

例如:

 runOnUiThread(new Runnable() { textView.setText("something."); }); or yourview.post(new Runnable() { yourview.setText("something"); }); 

这将帮助你更好地了解事情。 因此在你的情况下,你需要在onPostExecute()方法中设置你的textview。

我build议通过使用这个库进行后台工作,使你的生活更轻松https://github.com/Arasthel/AsyncJobLibrary

其简单..

 AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() { @Override public void doOnBackground() { startRecording(); } }); 

带POST请求的示例asynchronous任务:

 List<NameValuePair> params = new ArrayList<NameValuePair>(); params.add(new BasicNameValuePair("key1", "value1")); params.add(new BasicNameValuePair("key1", "value2")); new WEBSERVICEREQUESTOR(URL, params).execute(); class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String> { String URL; List<NameValuePair> parameters; private ProgressDialog pDialog; public WEBSERVICEREQUESTOR(String url, List<NameValuePair> params) { this.URL = url; this.parameters = params; } @Override protected void onPreExecute() { pDialog = new ProgressDialog(LoginActivity.this); pDialog.setMessage("Processing Request..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); super.onPreExecute(); } @Override protected String doInBackground(String... params) { try { DefaultHttpClient httpClient = new DefaultHttpClient(); HttpEntity httpEntity = null; HttpResponse httpResponse = null; HttpPost httpPost = new HttpPost(URL); if (parameters != null) { httpPost.setEntity(new UrlEncodedFormEntity(parameters)); } httpResponse = httpClient.execute(httpPost); httpEntity = httpResponse.getEntity(); return EntityUtils.toString(httpEntity); } catch (Exception e) { } return ""; } @Override protected void onPostExecute(String result) { pDialog.dismiss(); try { } catch (Exception e) { } super.onPostExecute(result); } } 
  private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); // Showing progress dialog progressDialog = new ProgressDialog(this); progressDialog.setMessage("Loading..."); progressDialog.setCancelable(false); progressDialog.show(); } @Override protected Void doInBackground(Void... arg0) { //do code here return null; } @Override protected void onPostExecute(Void result) { super.onPostExecute(result); // Dismiss the progress dialog if (progressDialog.isShowing()) { progressDialog.dismiss(); } } @Override protected void onCancelled() { super.onCancelled(); progressDialog.dismiss(); Toast toast = Toast.makeText(getActivity(), "Error is occured due to some probelm", Toast.LENGTH_LONG); toast.setGravity(Gravity.TOP, 25, 400); toast.show(); } } 

只是:

 LongOperation MyTask = new LongOperation(); MyTask.execute(); 

你需要声明buttononclicklistener,一旦点击它调用AsyncTask类DownloadJson,过程将显示如下:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button) findViewById(R.id.button1); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new DownloadJson().execute(); } }); } 

  // DownloadJSON AsyncTask private class DownloadJson extends AsyncTask<Void, Void, Void> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(Void... params) { newlist = new ArrayList<HashMap<String, String>>(); json = jsonParser.makeHttpRequest(json, "POST"); try { newarray = new JSONArray(json); for (int i = 0; i < countdisplay; i++) { HashMap<String, String> eachnew = new HashMap<String, String>(); newobject = newarray.getJSONObject(i); eachnew.put("id", newobject.getString("ID")); eachnew.put("name", newobject.getString("Name")); newlist.add(eachnew); } } } catch (JSONException e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void args) { newlisttemp.addAll(newlist); NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this,newlisttemp); newpager.setAdapter(newadapterpager); } } 

改变你的代码,如下所示:

 @Override protected void onPostExecute(String result) { runOnUiThread(new Runnable() { public void run() { TextView txt = (TextView) findViewById(R.id.output); txt.setText("Executed"); } }); } 

理论

AsyncTask允许您在后台线程上运行任务,同时将结果发布到UI线程。

用户应该始终能够与应用程序进行交互,避免阻止主(UI)线程执行诸如从Web下载内容等任务是非常重要的。 这是我们将使用AsyncTask

UI线程有一个消息队列和一个处理程序,允许您通常从其他线程发送和处理可运行的对象和消息。 AsyncTask用一个简单的接口来包装这个行为。

履行

AsyncTask是一个通用类。 (这意味着它的构造函数需要参数化的types,每个generics参数都被定义为一个带有三个点的Javavariables参数: ...所以在技术上作为数组传递)。

AsyncTask使用的三种types是ParamsProgressResult

  1. Params – 执行时发送给任务的参数types
  2. 进度 – 发布的types,用于在后台计算期间更新进度
  3. 结果 – 背景计算结果的types

这三个参数对应于您可以在AsyncTask重写的三个主要函数:

  • doInBackground()
  • onProgressUpdate()
  • onPostExecute()

    也:

  • onPreExecute()

执行AsyncTask

调用Execute带参数发送到后台任务。

怎么了

  1. 在主/ UI线程上, onPreExecute 。 (在这个线程中初始化一些东西。)
  2. 在后台线程中,使用传递给Execute函数的参数调用doInBackground()
    • 必须重写至lessdoInBackground()才能使用AsyncTask。
    • 长期的任务应该发生在哪里
    • 使用Progress参数调用publishProgress()以随着长时间运行的任务的进度更新一些UI。 这会导致onProgressUpdate()被调用。
  3. 在后台线程上,结果将从doInBackground()任务返回,这将导致
  4. 在main / UI线程上,用返回结果调用onPostExecute()

再次使用拦截任务的例子是从网上下载的东西,下面的例子下载一个图像,并将其显示在ImageView中。 doInBackground()方法下载图像并将其存储在BitMaptypes的对象中。 onPostExecute()方法获取位图并将其放置在ImageView中。

 class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { ImageView bitImage; public DownloadImageTask(ImageView bitImage) { this.bitImage = bitImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mBmp = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mBmp = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return mBmp; } protected void onPostExecute(Bitmap result) { bitImage.setImageBitmap(result); } }