zoukankan      html  css  js  c++  java
  • AsyncTask的异步线程的使用

    使用异步任务加载BItmap以及模仿Progressbar进度条的案例

    public class MainActivity extends AppCompatActivity {
        public Context context;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent=new Intent();
                    intent.setClass(MainActivity.this,ImageText.class);
                    startActivity(intent);
                }
            });
            Button button1= (Button) findViewById(R.id.button2);
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent=new Intent();
                    intent.setClass(MainActivity.this,ProgressBarTest.class);
                    startActivity(intent);
                }
            });
        }
    
    }

    设置监听事件分别调用两个不同的Activity,在第一个加载网络图片的Activity中需要用到网络,要在mainfest中设置用户访问网络的权限

    在设置监听事件中,使用Intent调用代码,使用的是6.0的api,需要将intent中的参数设置为(XXXX.this,XXXXX.class)才能解决无效指针的问题。

    加载网络图片的代码

    public class ImageText extends AppCompatActivity {
        private ImageView imageView;
        private ProgressBar progressBar;
        private static String URL="//img-my.csdn.net/uploads/201504/12/1428806103_9476.png";
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.imagetest);
            imageView=(ImageView) findViewById(R.id.image11);
            progressBar= (ProgressBar) findViewById(R.id.bar);
            new MyASyncTask().execute(URL);
        }
        class MyASyncTask extends AsyncTask<String,Void,Bitmap> {
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                //在已经加载过图片后Progressbar设置为不可见
                progressBar.setVisibility(View.GONE);
                //设置已经传入的网络图片bitmap
                imageView.setImageBitmap(bitmap);
                super.onPostExecute(bitmap);
            }
    
            @Override
            protected void onPreExecute() {
                //显示进度条
                progressBar.setVisibility(View.VISIBLE);
                super.onPreExecute();
            }
    
            @Override
            protected Bitmap doInBackground(String... strings) {
                //从excute中获得所传进来的string的值
                String url=strings[0];
                //必须初始化bitmap
                Bitmap bitmap = null;
                //设置网络连接的对象
                URLConnection connection;
                //设置输入流
                InputStream inputStream;
                try {
                    //获取网络连接对象,必须导入java.net.URL的包
                    connection=new URL(url).openConnection();
                    inputStream=connection.getInputStream();
                    Thread.sleep(3000);
                    //封装输入流
                    BufferedInputStream bis=new BufferedInputStream(inputStream);
                    //解析输入流
                    bitmap= BitmapFactory.decodeStream(bis);
                    //关闭输入流和封装流
                    inputStream.close();
                    bis.close();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }
                //返回所接受过的bitmap
                return bitmap;
            }
        }
        }

    写代码的思路梳理:

    通过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中开通所要访问的网络权限
    增加button调用

    ********************************************************************

    设置ProgressBar的代码

    public class ProgressBarTest extends AppCompatActivity {
        private MaysncTask mTask;
        private ProgressBar progressBar;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.progressbartest);
            //获取自定义内部类的AsyncTask的方法
            mTask=new MaysncTask();
            //运行这个方法
            mTask.execute();
            progressBar= (ProgressBar) findViewById(R.id.progressBar);
        }
    
        @Override
        //在activity退出前想保存用户重要数据的,必须在onPause中处理,因为当系统急需内存事,onStop和onDestroy是不会被执行的,
        protected void onPause() {
            super.onPause();
            if(mTask!=null&&mTask.getStatus()==AsyncTask.Status.RUNNING){
                mTask.cancel(true);
            }
        }
    
        class MaysncTask extends AsyncTask<Void,Integer,Void>{
            @Override
            protected void onProgressUpdate(Integer... values) {
                super.onProgressUpdate(values);
                //从doingbackground中得到所传入的值,为传入的整形数组values的第一个值,使用setprogress方法设置Progressbar的方法
                progressBar.setProgress(values[0]);
                if(isCancelled()){
                    //判断AsyncTask是否为cancel状态如果为cancel状态则return。return语句是将函数的值返回主调函数
                    return;
                }
            }
    
            @Override
            protected Void doInBackground(Void... voids) {
                for(int i=0;i<100;i++){
                    if(isCancelled()){
                        break;
                    }
                    //publishProgress() 更新进度,给onProgressUpdate()传递进度参数publishProgress传递的为整数
                    publishProgress(i);
                    try {
                        //设置延迟的效果300毫秒
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        }
        }

    在运行模拟Progress的运动的代码中出现没有办法停止前一个线程的解决办法:

    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

  • 相关阅读:
    Windows10字体模糊解决方法
    Synaptics触摸板在Windows10下双击弹出右键菜单无效的解决方法
    JDBC连接字符串及参数
    IntelliJ IDEA数据库工具连接MySQL提示Download missing driver files
    IntelliJ IDEA利用数据表生成JavaBean
    Windows下MySQL8.0的配置文件及数据库的默认目录
    MySQL配置说明
    (medium)LeetCode 221.Maximal Square
    (medium)LeetCode 222.Count Complete Tree Nodes
    (medium)LeetCode 224.Basic Calculator
  • 原文地址:https://www.cnblogs.com/edwardru/p/5901040.html
Copyright © 2011-2022 走看看