• Android必学——AsyncTask


    第一章  AsyncTask的基本构成

    为是么要异步任务

    1)Android单线程模型

    2)耗时操作放在非主线程中执行

    AsyncTask为何而生

    1)子线程中跟新UI

    2)封装、简化异步操作

     

    public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
    
        @Override
        protected Void doInBackground(Void... params) {//必须重写,其他方法没有规定必须重写
            // TODO 自动生成的方法存根
            Log.d("TAG", "doInBackground");
            publishProgress();//输入的参数会在onProgressUpdate()方法中获取到
            return null;
        }
    
        @Override
        protected void onPreExecute() {
            // TODO 自动生成的方法存根
            super.onPreExecute();
            Log.d("TAG", "onPreExecute");
        }
    
        @Override
        protected void onPostExecute(Void result) {
            // TODO 自动生成的方法存根
            super.onPostExecute(result);
            Log.d("TAG", "onPostExecute");
        }
    
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
            Log.d("TAG", "onProgressUpdate");
    }
    }
    //另类
    MyAsyncTask task=new MyAsyncTask();
    task.execute();//类似线程中的start()方法
    
    Ps:顺序:onPreExecute()->doInBackground(Params...)->调用publishProgress(Progress...)->onProgressUpdate(Progress...)->doInBackground(Params...)执行结束->onPostExecute(Result)

    第二章  AsyncTask的使用示例

    网络操作作为不稳定的废时操作,从android 4.0开始就被严禁放入主线程中
    通常采用在异步线程处理下载图像
    在UI线程设置图像
    
    ProgressBar XML属性 visibility="gone"可设置为默认状态下为隐藏
    VISIBLE:设置控件可见
    INVISIBLE:设置控件不可见
    GONE:设置控件隐藏
    
    而INVISIBLE和GONE的主要区别是:当控件visibility属性为INVISIBLE时,界面保留了view控件所占有的空间;而控件属性为GONE时,界面则不保留view控件所占有的空间。
    URLConnection connection //定义网络对象<br>
    ImputString is//定义用于获取数据的输入流<br>
    connection=new URL(url).openConnection();//获取网络连接对象<br>
    is= connection.getInputStream();//获得输入流<br>
    BufferedInputStream bis=new BufferedInputStream(is);//封装输入流<br>
    bitmap=BitmapFactory.decodeStram(bis);将输入流解析成bitmap<br>
    is.close();<br>
    bis.close();//关闭输入流<br>
    1.获取传递进来的参数值<br>
    string url=params[0];<br>
    2.访问网的操作<br>
    建立连接--设置输入流--封装输入流--decode输出流,转化为所需要的文件--关闭输入流和封装流
    最后将所需要的文件返回

    上述方法是写在doInBackground()里面的。

    通过OnProExcute方法和onPostExcute方法操作UI设置图像
    mProgressBar.setVisbility(View.VISIBLE)显示进度条
    onPostExcute(BitMap bitmap)//bitmap为doingbackground方法返回的一个bitmap
    在Main方法中,调用MyAsycTask的execute方法传入(URL)
    通过AsyncTask的实例调用execute方法就可以开启AsyncTask的异步操作,在execute方法中传入一个或多个参数作为我们doingbackground方法中所传进来的一个参数
    在AsyncTask的OnPreExecute方法中调用初始化的方法,在后台启动异步操作提示用户等待,调用真正的doingBackGround方法开始真正的异步处理,这里的整个方法都是现在子线程之中,在这个方法中进行所有的耗时操作,并将所要返回的值返回到我们所设定的值的类型中,在OnpostExecute方法中获得我们所返回的结果,onPostExcute方法也运行在主线程之中从而我们可以对UI进行操作,这就是AsyncTask所要调用的整个流程
    
    在Mainfest中开通所要访问的网络权限
    onPreExecute() 显示进度条
    onPostExcute()隐藏进度条 都可以访问UI线程
    mytask.execute(args)中传入的参数就是doInBackground中的参数
    onPreExecute--加载进度条
    doInBackGround--下载网络数据(耗时操作)
    onPostExecute--显示图片
    
    与UI线程通信
    在onPreExecute()方法中
    mProgressBar.setVisibility(View.VISIBLE);//显示进度条
    
    在onPostExectute(Bitmap bitmap)方法中,参数是doInBackground()方法返回的参数
    mProgressBar.setVisibility(View.GONE);//将进度条隐藏
    mImageView.setImageBitmap(bitmap);//将图片设置为解析出来的网络图片
    
    然后在onCreate方法中
    new MyAsyncTask().execute(URL);//开启AsyncTask的异步线程操作,设置传递进去的参数

    第三章  AsyncTask模拟进度条

    在AsyncTask的doInBackground()方法中调用publishProgress()方法可以将我们处理任务的进度反馈处理,
    我们这个时候就是用AsyncTask的onProgressUpdate()方法来承接我们传出来的进度,注意,由于在AsyncTask中,
    只有doInBackground()方法是工作在子线程中的,所以我们可以放心地在onProgressUpdate()方法中更新UI

    for(int i=0;i<100;i++){
    publishProgress(i);
    try{
    Thread.sleep(300);
    } catch(InterruptedException e){
    e.printStackTrace();
    }
    }
    
    onProgressUpdate(Integer...values){
    super.onProgressUpdate(values);
    //获取进度更新值
    mProgressBar.setProgress(values[0]);
    }
    AsyncTask默认情况下会等待前一个线程执行完毕后再执行下一个线程,要取消该机制,可以让AsyncTask和Activity的生命周期保持一致
    protected void onPause(){
    super.onPause();
    if(mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING){
    //只是发送了一个取消请求,将AsyncTask标记为cancel状态,但未真正取消线程的执行
    //实际上JAVA语言没办法粗暴地直接停止一个正在运行的线程
    mTask.cancel(true);
    }
    }
    
    所以需要在doInBackground方法和onProgressUpdate方法中增加isCancelled()方法进行判断,标记为cancel的,则跳出循环,尽快结束当前线程的剩余操作,开始下一个线程
    
    AsyncTask实现的机制:底层通过线程池来作用的,当我们一个线程没有执行完毕时,后面的线程是无法执行的;
    调用cancel方法去cancel一个asynctask线程,并没有将这个线程直接停止掉,只是给这个asynctask发送了一个cancel请求,将它标识为cancel状态;
    在java中是无法直接将一个线程粗暴地停止掉,我们必须等一个线程执行完毕后才能做后面的操作。(需通过状态值判断去跳出子线程的循环操作)
    
    只有doInBackground是在非UI线程中执行
    mytask!=null&&mytask.getStatus()== AsyncTask.Status.RUNNING
    ansystask 即使cancel设置为true 也不能立即取消,只是将状态设为取消
    故在doInBackground和onUpdatexx的时候检测isCancled()是不是true

     

    doInBackground()方法运行在非主线程,其他三个方法运行在主线程,所以可以在doInBackground做异步操作,在其他三个方法中更新UI。
    正是因为有了onProgressUpdate()和onPostExcute()方法,才可以在异步处理的过程中更新UI。
  • 相关阅读:
    js对象
    _proto_和prototype区别
    手写自己的Vuex
    limitPNG压缩图片
    swiper兼容性ie浏览器出现的问题
    postcss-pxtorem
    【Other】Win10防火墙放行Docker(WSL2)端口
    docker容器内使用apt-get报错
    docker+mysql
    docker部署+验证码错误
  • 原文地址:https://www.cnblogs.com/jingmengxintang/p/5904148.html
Copyright © 2020-2023  润新知