AsyncTask

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AsyncTask相关的知识,希望对你有一定的参考价值。


简介
技术分享
AsyncTask简介 android提供了一个Handler来处理子线程和UI线程的通讯,用发消息的方式更新UI界面,呈现给用户。 但是费时的任务操作总会启动一些匿名的子线程,太多的子线程会给系统带来巨大的负担,随之带来一些性能问题。 因此android又提供了一个工具类AsyncTask来异步执行任务。 AsyncTask对线程间的通讯进行了包装,提供了简易的编程方式来使后台线程和UI线程进行通讯:后台线程执行异步任务,并把操作结果通知UI线程。 这个AsyncTask生来就是处理一些后台的比较耗时的任务,不再需要子线程和Handler就可以完成异步操作并且刷新用户界面。
AsyncTask和Handler优缺点 1、AsyncTask是android提供的【轻量级】的异步类,适用于简单的异步处理。相比较效率更高(有线程池的概念)但也更耗资源 优点:简单,快捷;过程可控; 缺点:在使用【多】个异步操作并需要进行Ui变更时,就变得复杂起来. 2、Handler承担着接受子线程用sedMessage()方法传递的Message, 把这些消息放入主线程队列中,配合主线程进行更新UI。 优点:结构清晰,功能定义明确;对于【多】个后台任务时,简单,清晰 缺点:在单个后台异步处理时,显得代码过多,结构过于复杂(相对性) 3、数据简单使用AsyncTask:实现代码简单,数据量多且复杂使用handler+thread

三个泛型参数
AsyncTask<Params, Progress, Result> 
    Params, the type of the parameters sent to the task upon execution.
    Progress, the type of the progress units published during the background computation.
    Result, the type of the result of the background computation.
Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:

① Params 是doInBackground()的参数类型;
② Progress 是onProgressUpdate()的参数类型;
③ Result 是doInBackground()的返回值类型,也是onPostExecute()的参数类型;

代码
public class MainActivity extends ListActivity {
    private ProgressDialog dialog;
    private TextView tv_info;
    private String[] urls = { "http://www.sinaimg.cn/dy/slidenews/3_img/2016_22/77542_379696_802603.jpg",
            "http://www.sinaimg.cn/dy/slidenews/3_img/2016_22/77542_379697_224394.jpg""http://www.sinaimg.cn/dy/slidenews/3_img/2016_22/77542_379700_726793.jpg",
            "http://www.sinaimg.cn/dy/slidenews/3_img/2016_22/77542_379703_690557.jpg""http://www.sinaimg.cn/dy/slidenews/3_img/2016_22/77542_379710_990624.jpg",
            "http://tupian.qqjay.com/u/2013/1127/19_222949_14.jpg""http://pic2.sc.chinaz.com/files/pic/pic9/201605/apic20643.jpg",
            "http://tupian.qqjay.com/u/2013/1127/19_222949_10.jpg""http://pic.sc.chinaz.com/files/pic/pic9/201603/fpic430.jpg" };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        List<String> mData = new ArrayList<String>(Arrays.asList("使用AsnycTask在后台执行耗时操作,并更新UI(TextView和Dialog)""异步加载网络图片"));
        ListAdapter mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mData);
        tv_info = new TextView(this);// 将内容显示在TextView中
        tv_info.setTextColor(Color.BLUE);
        tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
        tv_info.setPadding(20, 10, 20, 10);
        getListView().addFooterView(tv_info);
        setListAdapter(mAdapter);
    }
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        switch (position) {
        case 0:
            new MyAsnycTask().execute("这是参数");//必须在UI 线程中创建AsnycTask的实例,必须在UI 线程中调用execute方法,且只能被执行一次
            break;
        case 1:
            new MyImageLoadTask().execute();//大约执行5次左右就会OOM
            break;
        }
    }
    class MyAsnycTask extends AsyncTask<String, Integer, Object> {
        @Override
        protected void onPreExecute() { //准备工作, 在执行实际的后台操作前在【UI 线程】中执行,这个方法可以不用实现
            super.onPreExecute();
            Log.i("bqt""onPreExecute");
            tv_info.append("\\nonPreExecute");
            dialog = new ProgressDialog(MainActivity.this);
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setMax(100);
            dialog.setTitle("提示");
            dialog.setMessage("当前正在玩命加载中,请稍后 ... ");
            dialog.setIcon(android.R.drawable.ic_menu_info_details);//这里指的是标题左侧的图标。注意:如果没有设置title只设置Icon的话,是不会显示图标的  
            dialog.setCancelable(false);
            dialog.show();
        }
        @Override
        protected Object doInBackground(String... params) { // 将在onPreExecute执行后立即执行,该方法运行在【子线程】中,负责执行耗时的后台工作
            Log.i("bqt""doInBackground");
            String str = params[0];//【String...】其实是一个String类型的可变长度的【数组】
            for (int i = 0; i < 100;) {
                try {
                    Thread.sleep(150);//模拟耗时操作。也可以用SystemClock.sleep(50);//不需要try catch
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i += new Random().nextInt(10);
                if (i > 100) i = 100;
                Log.i("bqt""doInBackground-" + i);
                publishProgress(i);//实时更新任务进度,每调用一次就会调用一次onProgressUpdate方法
            }
            return str + "_玩命加载成功";//返回的结果将作为参数传递给onPostExecute
        }
        @Override
        protected void onProgressUpdate(Integer... values) { // 在publishProgress方法被调用后回调,方法运行在【UI 线程】中
            super.onProgressUpdate(values);
            int position = values[0];
            Log.i("bqt""onProgressUpdate-" + position);
            tv_info.append("\\nonProgressUpdate-" + position);
            dialog.setProgress(position);
        }
        @Override
        protected void onPostExecute(Object result) { //在doInBackground 执行完成后,将其返回值作为参数传递过来,运行在【UI 线程】中
            super.onPostExecute(result);
            Log.i("bqt""onPostExecute-" + result);
            tv_info.append("\\nonPostExecute");
            dialog.cancel();
            dialog.dismiss();
        }
        @Override
        protected void onCancelled() {//取消线程操作时调用。运行在【UI 线程】中
            super.onCancelled();
            Log.i("bqt""onCancelled");
        }
    }
    //******************************************************************************************
    class MyImageLoadTask extends AsyncTask<Void, Bitmap, Void> {
        protected Void doInBackground(Void... params) {
            for (int i = 0; i < urls.length; i++) {
                SystemClock.sleep(1500);//让他睡一会
                Bitmap bitmap = BitmapFactory.decodeStream(getInputStream(urls[i]));//得到网络图片
                publishProgress(bitmap); // 通知去更新UI
            }
            return null;//注意:因为返回值是【Void】类型,而不是【void】无返回值,所以一定要写这一句!
        }
        public void onProgressUpdate(Bitmap... bitmaps) {
            if (!isCancelled()) {//Returns true if this task was cancelled before it completed normally. 
                ImageView imageView = new ImageView(MainActivity.this);
                imageView.setImageBitmap(bitmaps[0]);
                getListView().addFooterView(imageView);
                getListView().smoothScrollToPosition(getListView().getCount() - 1);//移动到尾部
                //Smoothly平滑地 scroll to the specified指定 adapter position. The view will scroll such that the indicated指示的 position is displayed.
            }
        }
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            Toast.makeText(MainActivity.this"加载完毕……", Toast.LENGTH_SHORT).show();
        }
    }

    /** 给我一个url,还你一个流 */
    public static InputStream getInputStream(String url) {
        try {
            URLConnection conn = new URL(url).openConnection();
            conn.setConnectTimeout(3 * 1000);
            return conn.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}












以上是关于AsyncTask的主要内容,如果未能解决你的问题,请参考以下文章

片段中的 Asynctask 未到达 onPostExecute

在 AsyncTask 中将新的 TextView 设置为片段

AsyncTask 和 FragmentManager 的问题

用 Asynctask 更新 FragmentTransaction 替换的片段

从Asynctask ONPostExecute调用片段方法

在 Asynctask 的 onPostExecute() 方法中更改片段