android提供了几种在其他线程中访问UI线程的方法。 Activity.runOnUiThread( Runnable ) View.post( Runnable ) View.postDelayed( Runnable,long ) Hanlder 这些类或方法同样会使你的代码很复杂很难理解。然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。 为了解决这个问题,Android 1.5提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单。相对来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和Handler即可实现。 AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。 Params 启动任务执行的输入参数,比如HTTP请求的URL。 Progress 后台任务执行的百分比。 Result 后台执行任务最终返回的结果,比如String。 AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。 1) 子类化AsyncTask 2) 实现AsyncTask中定义的下面一个或几个方法 onPreExecute(),该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。 doInBackground(Params...),将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。 onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。 onPostExecute(Result),在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread. 为了正确的使用AsyncTask类,以下是几条必须遵守的准则: 1) Task的实例必须在UI thread中创建 2) execute方法必须在UI thread中调用 3) 不要手动的调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)这几个方法 4) 该task只能被执行一次,否则多次调用时将会出现异常 doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。
下面结合一个解析xml文件简单的例子来说明其用法:
MainActivity.java文件:
public class MainActivity extends ListActivity implements OnClickListener{ private ProgressBar progressBar; public static final int WRODS_COUNT = 1; public static final int WORD = 2; private List<String> list; private ArrayAdapter<String> wordAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); progressBar = (ProgressBar) findViewById(R.id.progress_bar); findViewById(R.id.start_btn).setOnClickListener(this); list = new ArrayList<String>(); wordAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list); setListAdapter(wordAdapter); } @Override public void onClick(View v) { asynTask.execute();//启动异步处理类对象 } private AsyncTask<XmlResourceParser,String,Void> asynTask = new AsyncTask<XmlResourceParser,Void>(){ private int count = 0; /*第一个在Main线程执行的AsyncTask方法,用来做初始化 onPreExecute(),该方法将在执行实际的后台操作前被UI thread调用。 可以在该方法中做一些准备工作,如在界面上显示一个进度条。*/ protected void onPreExecute() { Log.i("info","-->onPreExecute"); }; /*在doInBackground方法中调用publishProgress方法后,在Main线程中执行此方法 一般用来呈现处理进度 在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况, 例如通过一个进度条进行展示。*/ protected void onProgressUpdate(String...values) { if(count != 0){ progressBar.setMax(count); } list.add(values[0]); progressBar.setProgress(progressBar.getProgress()+1); wordAdapter.notifyDataSetChanged(); setTitle("完成:"+progressBar.getProgress()*5+"%"); }; /*doInBackground将在onPreExecute 方法执行后马上执行, 该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。 可以调用 publishProgress方法来更新实时的任务进度。 该方法是抽象方法,子类必须实现。*/ @Override protected Void doInBackground(XmlResourceParser... params) { // TODO Auto-generated method stub //获取要解析的文档 Log.i("info","-->doInBackground"); Resources res = getResources(); XmlResourceParser xrp = res.getXml(R.xml.wrods); while(true){ int flage = 0;//用于记录标签的类型 try { flage = xrp.next(); if(flage == XmlPullParser.END_DOCUMENT) break; if(flage == XmlPullParser.START_TAG){ String tagName = xrp.getName(); if("words".equals(tagName)){ /*count用于记录有多少条数据, *xrp.getAttributeValue(0)用于获取标签名为words的属性值 **/ count = Integer.parseInt(xrp.getAttributeValue(0)); } if("word".equals(tagName)){ String text = xrp.nextText(); publishProgress(text); } /*注意:sleep()方法是线程类的方法,调用时需要加上类来调用*/ Thread.sleep(500); } } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } /*最后一个在Main线程中执行的方法,一般控制试图控件显示结果内容 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用, 后台的计算结果将通过该方法传递到UI thread*/ protected void onPostExecute(Void result) { Log.i("info","-->onPostExecute"); }; }; }
布局文件比较简单就不写了,这个例子只是简单说明异步处理,在代码上不规范,仅供参考!
运行效果如图所示: (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|