AsyncTask源码分析

AsycTask   

维护了一个线程池   看源码可发现它有一个最大线程和最小线程数 分别为(128和5)   ,但是这是一个不准确的,最大线程数应该取决于你的CPU   首先它会获取你的CPU数量, 如果你的CPU为双核最大线程数应该为   (2*CPU数量+1)   ,核心线程是你的CPU数量

当使用的线程数量越多,栈的资源也就越大,对手机的消耗也就越大,同样电量的消耗也会变大,手机发热量大,比如:当用户不断的刷新listview,抓取服务端的图片资源,显示在用户端的时候,开得线程数量也就越大,会出现以上问题。如何进行低资源消耗呢?根本原因就是开出的手机线程数太大,CPU计算能力就增大,可以去控制线程数,用线程池来解决!

一: AncycTack task;

task.execute(parms);

当执行这个方法的时候  调用的是内部自己的线程池

task.executeOnExecutor(exec, params)

当执行这个方法的时候,是自己自定义的线程池

两者有什么重要的区别呢?

 内部的线程池的缺陷:

必须在一个线程完成所有的工作之后才去执行下一个线程的操作

API源码如下:  大概知道为什么了吧?同步机制

  public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });

应用在哪里呢?

 比如当你下载图片,并显示图的时候  每个listview条目都需要 task.execute(parms)的话

 第一个条目完全显示了,第二个条目图片资源才会显示,这种现象我们不希望发生,我们希望整个界面的listview图片资源都在同时下载显示,我们就需要使用

task.executeOnExecutor(exec, params) 不会被同步所限制

但是需要考虑CPU线程池数量的问题了。

bitmap-utils这个框架给我们解决的这类的问题,当是我们程序猿不能只知道怎么去使用框架,还要知道最原始的技术,才能得到提高,有兴趣可以看看x-utils源码,!!!

二:异步任务给我们封装了handler+message 让我们来看看如何封装的:

源码 如下 :

    private static class InternalHandler extends Handler {
        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:

//自动调用异步中的protected void onProgressUpdate(Void... values) {......}
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }

 封装了一个静态的handler 为什么异步任务,封装的是静态的,而我们写代码的时候没有声明静态的(没有声明静态会导致内存泄漏),而我们却不去声明呢?

声明静态的话,静态的内部类调用外部类的方法字段很麻烦

       为什么会导致内存泄漏呢?

      当这个应用关闭的时候 handler+message还在不断的发消息,静态的内部类还持有外部类的引用this,这个activity不会立即被销毁,内存中还持有这个对象,就会导致内存泄漏

 

就会调用 

private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);//倒是异步任务中onPostExecute方法的调用
        }
        mStatus = Status.FINISHED;
    }


  result.mTask.onProgressUpdate(result.mData);的调用

一旦执行一个数据结果的时候就会调用:onProgressUpdate来更新进度

所以你才会看到 进度条的不断更新




只有doInBackground(...)运行在子线程中,耗时操作,其它三个方法运行在主线程中

但是doInBackground(...) 如何完成在子线程中,进行耗时操作的呢?

如下四个方法的执行顺序如下:

先执行准备--->子线程中执行数据,耗时操作--->执行数据的时候显示的进度--->执行完成后

new AsyncTask<Void, Void, Void>(){
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
return null;
}

@Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}

};

这个doInBackground方法什么时候,如何调用的:

四个方法的调用一定要结合handler+message 

  doInBackground:被调用的位置 ,方法

 public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //noinspection unchecked
                return postResult(doInBackground(mParams));
            }
        };

WorkerRunnable 继承了 Runnable

所以是在子线程中被调用了、


小知识点: 主线程可以进行耗时操作和子线程可以GUI么?

可以,但是一般没人去这么做

比如:

tv=(Textview)findViewById(R,id,tv);

new Thread(new Runnable(){

public void run{

tv.settext("跟新GUI");

}

}).start();




希望这些内容会对读者有帮助!!!!





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值