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个步骤:
- onPreExecute()
- doInBackground(参数…)
- onProgressUpdate(进展…)
- 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是Params
, Progress
和Result
:
- Params – 执行时发送给任务的参数types
- 进度 – 发布的types,用于在后台计算期间更新进度
- 结果 – 背景计算结果的types
这三个参数对应于您可以在AsyncTask
重写的三个主要函数:
-
doInBackground()
-
onProgressUpdate()
-
onPostExecute()
也:
-
onPreExecute()
执行AsyncTask
调用Execute
带参数发送到后台任务。
怎么了
- 在主/ UI线程上,
onPreExecute
。 (在这个线程中初始化一些东西。) - 在后台线程中,使用传递给Execute函数的参数调用
doInBackground()
。- 必须重写至less
doInBackground()
才能使用AsyncTask。 - 长期的任务应该发生在哪里
- 使用
Progress
参数调用publishProgress()
以随着长时间运行的任务的进度更新一些UI。 这会导致onProgressUpdate()
被调用。
- 必须重写至less
- 在后台线程上,结果将从
doInBackground()
任务返回,这将导致 - 在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); } }