美文网首页
异步任务AsyncTask下载图片

异步任务AsyncTask下载图片

作者: Mr_LJ | 来源:发表于2016-07-09 18:56 被阅读321次

    一:ANR现象:

    ==应用程序无响应<Application not Responsed>==

    1.单线程模型的原则:
    • 主线程UI不能被阻塞
    • 非主线程不能更新UI
    public class MainActivity extends Activity{
        private TextView textView;
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInatanceState);
            setContentView(R.layout.main_activity);
            //违反第二原则:在非主线程更新UI
            //CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            new Thread(){
                public void run(){
                    int count = 0;
                    while(count < 100){
                        count ++ ;
                        try{
                            Thread.sleep(1000);
                        }
                        catch(Exception e){
                            e.printStackTrace;
                        }
                        //在非UI线程更新UI
                        textView.setText("当前count:"+count);
                    }
                };
            }.start();
        }
        
        //违反第一个原则,导致ANR现象出现
        public void click(View view){
            try{
                Thread.sleep(6000);
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    二.AsyncTask的基本使用

    1.自定义一个类继承系统的AsyncTask,其参数说明如下:
    • Params:启动异步任务执行的输入参数 例如HTTP请求的URL一般是String类型
    • Progress:后台执行任务的百分比 通常是Integer类型
    • Result:后台执行任务最终返回的结果
      ==注意:AsyncTask的执行分为四个步骤 每一步都对应一个回调方法(由应用程序自动调用的方法) 开发者需要做的就是实现这些方法==
    2.为了正确的使用AsyncTask类,必须遵守以下几条准则:
    • AsyncTask的实例必须在UI线程中创建
    • execute方法必须在UI线程中调用
    • 不要手动去调用onPreExecute() doInBaground() onProgressUpdate() onPostExecute()
    • AsyncTask的实例只能被执行一次 多次调用的时候将会出现异常

    ==代码:首先自定义一个类实现系统AsyncTask,异步图片下载:==

    public class MyAsyncTask extends AsyncTask<String , Void , Bitmap>{
        //上下文对象
        private Context context;
        private ProgressDialog dialog;
        private ImageView imageView;
        
        //构造
        public MyAsyncTask(Context context , ImageView imageView){
            super();
            this.context = context;
            this.imageView = imageView;
        }
        
        /**
         * 实现四个系统回调的方法
         */
         
        /**
         * 1.onPreExecute()方法:在后台执行前的准备工作,主线程调用
         * 准备工作:做什么?>创建进度对话框
         */
        @Override
        protected void onPreExecute(){
            super.onPreExecute();
            dialog = new ProgressDialog();
            dialog.setIcon(R.drawable.xxx);
            dialog.setTitle("友情提示!");
            dialog.setMessage("正在玩命为您加载中");
            //下面show()方法不要忘了,否则不显示进度对话框
            dialog.show();
        }
        
        /**
         *  2.doInBackground()方法:非主线程调用,后台的主要工作线程,
         *  如耗时的操作(网络下载图片,下载JSON等)都放在这里执行。
         *  它是子线程,不可以在这里做UI操作(重要)
         *  参数是String类型字符数组,通常为传入的url
         */
        @Override
        public void doInBackground(String...params){
            //网络请求:
            /*创建HttpClient的实例*/
            HttpClient httpClient = new DefaultHttpClient();
            /*创建连接方法的实例,HttpGet()的构造中传入url地址*/
            HttpGet httpGet = new HttpGet(params[0]);
            try{
                /*调用创建好的HttpClient的实例的execute方法来发送创建好的HttpGet或HttpPost请求,并返回HttpResponse对象*/
                HttpResponse httpResponse = httpClient.execute(httpGet);
                if(httpResponse.getStatusLine().getStatusCode() == 200){
                    /*返回实体对象*/
                    HttpEntity entity = httpResponse.getEntity();
                    byte [] data = EntityUtils.toByteArray(entity);
                    Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);
                    return bitmap;
                }
            }
            catch(Exception e){
                e.printStackTrace();
            }
            finally{
                httpClient.getConnectionManager().shutdown();
            }
        }
        
        /**
         *  更新显示进度,主线程调用
         */
        @Override
        public void onProgressUpdate(Void...values){
            super.onProgressUpdate(values);
        }
        
        /**
         *  在doInBackground执行完成之后调用,后台的计算结果将通过该方法传递到UI线程,回到主线程(主线程调用的)
         *  可以实现主线程和子线程之间的数据交互
         */
        public void onPostExcute(Bitmap bitmap){
            super.onPostExecute(bitmap);
            if(bitmap != null){
                imageView.setImageBitmap(bitmap);
            }
            else{
                Toast.makeText(context,"下载图片失败",Toast.LENGTH.LONG).show();
            }
            //关闭进度对话框
            dialog.dismiss();
        }
    }
    

    测试代码:

    public class MainActivity extends Activity{
        private ImageView imageView;
        private MyAsyncTask myAsyncTask;
        private String url = "";http://p5.qhimg.com/dmt/490_350_/t01405cf23f986e5ef6.jpg
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main_activity);
            
            imageView = (ImageView)findViewById(R.id.iv_imageview);
            //创建AsyncTask的实例
            myAsyncTask = new MyAsyncTask(this,imageView);
        }
        
        //点击按钮,开始异步下载图片
        public void downloadPic(View view){
            /*AsyncTask的实例只能被执行一次*/
            myAsyncTask.execute(url);
        }
    }
    

    相关文章

      网友评论

          本文标题:异步任务AsyncTask下载图片

          本文链接:https://www.haomeiwen.com/subject/lwzrjttx.html