AsyncTask小案例
2015-08-22 12:17
381 查看
AsyncTask小案例
△关于安卓里的异步任务
→安卓里的异步任务,可以当做java里面的多线程来看待了,在java语言里,想要启动多线程就只有两个方法:继承Thread类并重写run()方法,或者实现Runnable接口并且重写run()方法。→安卓里面,想要启动多个线程可以通过:1,java原来有的两个方法(Thread类和Runnable接口);2,Handler类提供方法启动异步任务;3,AsyncTask类也能实现异步任务;4,IntentService类(Service的子类)也能实现异步任务,虽然这个和上述的相比有些勉强。
△为什么需要使用AsyncTask
Handler类提供很完整的异步任务机制,但是他的使用相对复杂,对于刚刚入手安卓的人来说,不好理解,AsyncTask的底层也是通过Handler来实现,通过封装,相对来说比较能让新手使用,简单方便。△关于安卓的单线程模型
虽说AsyncTask封装的很好,能让你几乎在不了解安卓多线程工作的具体情况之下,照样使用异步任务,但是如果想理解好异步任务,还得说说安卓的某些线程的知识。理解这些知识以后,对于理解AsyncTask使用的注意事项,也更方便。
→主线程与UI线程:安卓应用在启动时,就是启动一个进程,这个进程可能会有若干线程,其中有个就是所谓“主线程”,他又叫做UI线程,首先记住:UI线程==主线程。
→安卓的单线程模型:详细情况你可以在网上查到,我在这里说说一定要记住的:
(1)不要阻塞UI线程:别在UI线程里面进行耗时操作(一般就是不要执行超过五秒钟的操作),否则将会出现ANR对话框(应用程序没有响应 )。
(2)只能够在主线程里更新UI:所有对UI的更新(比如修改TextView显示内容,修改ImageView的图片),都只能在主线程里进行,因为安卓对UI的操作是线程不安全的,如果你在非UI线程里更新UI,会抛异常。
△AsyncTask的简介
→他是个类,而且还是个抽象类,一个安卓封装好的用来简化异步任务的类,只有继承了并指定泛型参数,覆写指定的方法后才能使用,使用他,你能在几乎不了解安卓系统多线程的工作过程的前提下,使用安卓多线程的功能。→类原型:public abstract class AsyncTask<Params, Progress,Result>,三个泛型参数的功能分别是:
(1)Params:启动后台任务时的输入参数,比如你要下载一些文件,那参数是这些文件的URI。
(2)Progress:任务执行过程中更新进度的参数,比如传给进度条的参数。
(3)Result:任务执行完成之后所返回的结果。
→主要方法:
(1)protected abstract Result doInBackground(Params... params);
这是必须要实现的方法,所有异步任务都在里面这些执行,同时,该方法的所有代码都运行在非UI线程里,根据刚才所说到的单线程的模型,这个方法里面绝对不能进行任何对UI的操作。
(2)protected void onPreExecute();
异步任务执行前的准备操作,该方法在异步任务正式启动之前被回调(doInBackground()方法执行之前回调),该方法的所有代码都执行在UI线程里面,这里可以进行UI操作,比如,将进度条的进度值设置为零。但是这里不能进行耗时操作,因为是在UI线程。
(3)protected void onProgressUpdate(Progress... values);
任务执行过程中更新UI的操作,当你在"doInBackground()"方法里面调用函数"publishProgress(Progress... values)",实际执行的代码是"onProgressUpdate(Progress... values)"方法里面所写代码。这个方法里的所有代码都运行在UI线程里,可以进行更新UI操作,但是不能进行耗时操作。
(4)protected void onPostExecute(Result result);
当异步任务正常结束后(doInBackground()方法运行结束之后),这个方法将被回调,该方法的所有代码都运行在UI线程,可以在这进行完成任务相关提示,这里不能进行耗时操作,注意:如果异步任务是被取消掉的,这个方法不会执行。
AsyncTask类方法小结
(1)异步任务各个方法执行顺序:onPreExecute()→doInBackground()→onProgressUpdate()(如果调用过publishProgress方法)→onPostExecute()。
(2)除了doInBackground()方法里的代码是运行在子线程里面的,其与方法的代码是跑在UI线程里面。
△AsyncTask使用注意
→一个AsycnTask实例只能被执行一次(只能够execute()一次),第二次会出现异常。→刚才提到所重写的四个方法,都不能有开发者所调用,都不能有开发者所调用,都不能有开发者所调用,重要的事情说三遍,只能重写,他们都有系统调用。
△示例代码
下面来看看实例了,模拟一个文件下载效果,布局文件很简单的,先来看看布局文件代码:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/tv_print_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="正下载第0个文件" android:gravity="center_horizontal" android:textSize="24sp" /> <Button android:id="@+id/btn_star_asyncTask" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动一个异步任务" android:onClick="asyncTask"/> <Button android:id="@+id/btn_pauseAsyncTask" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="取消当前异步任务" android:onClick="asyncTask"/> <ProgressBar style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/progressBar" /> </LinearLayout>
再来看看窗体代码:
package com.example.masynctask; import android.app.Activity; import android.os.AsyncTask; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import java.io.File; import java.io.InputStream; public class MainActivity extends Activity { //准备数组待会传递异步任务 private String[] strings = new String[]{"一号文件","二号文件","三号文件","四号文件"}; private TextView textView = null;//这个用来更新窗体 private ProgressBar progressBar = null;//进度 private MAsyncTask mAsyncTask = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.tv_print_content); progressBar = (ProgressBar)findViewById(R.id.progressBar); } public void asyncTask(View view){ switch(view.getId()) { case R.id.btn_star_asyncTask: mAsyncTask = new MAsyncTask(); mAsyncTask.execute(strings); break; case R.id.btn_pauseAsyncTask: mAsyncTask.cancel(true); break; } } // 第一参数:执行时传递进去的类型 // 第二参数:更新那时用的参数 // 第三参数:结束那是传递进去"onPostExecute"方法的参数 //AsyncTask里面的泛型,和上述所介绍哪些方法里的泛型,是对应的。 private class MAsyncTask extends AsyncTask<String,Integer,Integer>{ @Override protected Integer doInBackground(String... params) { Log.i("test", "doInBackGround"); int i = 0; while(i<params.length) { publishProgress(i,params.length); try { Thread.sleep(4000L); } catch (Exception e) { e.printStackTrace(); } i++; if (isCancelled()){ break; } } Log.i("test","循环结束"); return params.length; } // 这个方法将在子线程开始前执行 @Override protected void onPreExecute() { super.onPreExecute(); Log.i("test","onPreExecute"); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); // Log.i("test","正在下载第"+values[0]+"个文件"); textView.setText("正下载第"+values[0]+"文件"); progressBar.setProgress( (int)((values[0]+1)/(float)values[1]*100) ); } // 这个方法将执行在异步任务结束之后 @Override protected void onPostExecute(Integer integer) { super.onPostExecute(integer); Log.i("test", "onPostExecute"); } @Override protected void onCancelled(Integer integer) { super.onCancelled(integer); Log.i("test", "onCancelled"); } }
相关文章推荐
- POJ2667 Hotel(线段树区间合并)
- 基于MDK编程STM32程序无法使用,硬件仿真在汇编窗口看到停留在“0x0800XXXX BEAB BKPT 0xAB //进入调试模式”
- Selection使用简介
- 爬虫Larbin解析(一)——Larbin配置与使用
- 2014扬声器的信息中国建筑师大会
- 第 4 章 Android 应用的调试
- pat(B)1009. 说反话(逆迭代器)
- MySQL 主键与索引的联系与区别分析
- 接口隔离原则(ISP)
- 栈的应用1——超级计算器(中缀与后缀表达式)C语言
- jquery实现很酷的网页顶部图标下拉菜单效果
- Excel一项研究指出色彩
- 【LeetCode】264. Ugly Number II
- java获取list集合转换成json数据
- hbase0.94.14+hadoop2.6.0
- 第2期Spark纯实战公益大讲坛:通过案例实战掌握Spark编程模型内幕
- ubuntu中,如何把安装的软件启动图标加到桌面上
- web开发常用正则表达式
- 在Linux系统中chowna+x 与chmod o+x有什么区别
- LayoutInflater.inflate方法解析