A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 石头哥 于 2017-5-27 18:34 编辑

         对于加载图片,大家都不陌生,大多数都是为了尽可能避免OOM的Bug,都会按照如下做法:
              (1)对于图片显示:根据需要显示图片控件的大小对图片进行压缩显示。
              (2)如果图片数量非常多:则会使用LruCache等缓存机制,将所有图片占据的内容维持在一个范围内。


         其实对于图片加载还有种需求 ,就是单个图片非常巨大,并且还不允许压缩。比如显示:世界地图、清明上河图、微博长图等。
         比如下面的需求:


       那么对于这种需求,该如何做呢?


方法一.使用subsampling-scale-image-view库
  
身为一名开发经验丰富程序猿, 第一反应是去Google
上搜索一下!!!
果然不负众望
,
可以直接使用subsampling-scale-image-view这个库, 轻松实现 ,心情愉快



方法二:使用Glide+Bitmap

   然而, 我们仅仅只是想实现超长图片的展示效果, 为此附带其它的一些无用代码, 就会增加我们app的大小,subsampling-scale-image-view主要是使用了Google的开源图片加载框架Glide, 先使用Glide将图片下载到本地, 然后转换成Bitmap再显示的思路, 只是在这个核心功能上增加了手势操作功能, 所以不如我们自己使用Glide来实现这个功能


         
[Java] 纯文本查看 复制代码
          Glide.with(this).load(RequestUrl.BASE_URL + photoUrl)
                  .downloadOnly(new SimpleTarget<File>() { 
                         @Override 
                         public void onResourceReady(File resource, GlideAnimation<? super File> glideAnimation) { 
                         // 将保存的图片地址给 SubsamplingScaleImageView,这里注意设置ImageViewState设置初始显示比例 
                         Bitmap bitmap= BitmapFactory.decodeFile(resource.getAbsolutePath(),getBitmapOption(1)); 
                         // 显示处理好的Bitmap图片 
                         imageView.setImageBitmap(bitmap); 

                   }                  
           });         
          


     但是仅仅这样似乎还不够,图片并没有显示成我们预想的那样,

     此处是重点---->ImageView有个属性, adjustViewBounds属性,这个属性的作用为是否让图片保持宽高比, 设置它为true


         
[AppleScript] 纯文本查看 复制代码
          android:adjustViewBounds="true"
          


     效果完美显示, 问题解决


方法三.使用HttpUrlConnection + Bitmap
   根据方法二, 可以推测一下,是不是只要是将图片下载到本地然后转化成bitmap,都能够解决这个问题呢?, 所以试试HttpUrlConnection来下载图片最后显示的办法

[Java] 纯文本查看 复制代码
 
        /** 点击获取图片 
         * @param view  
         */
        public void start(View view) {    
              final String path = "http://192.168.3.162:8080/gotoclass/test.jpg";
              new ShowLongImgAsyncTask().execute(path);
        }
 
        /** 
         * 自定义AsyncTask 
         */
       class ShowLongImgAsyncTask extends AsyncTask<String, Void, File> {    
            @Override    
             protected void onPreExecute() {        
                  super.onPreExecute();        
                  imageView.setImageBitmap(null);
             }    
       
            @Override
            protected void onPostExecute(File result) {
                  super.onPostExecute(result); 
                  if (result != null) {
                        if (file != null && file.exists()) {
                              Bitmap bitmap = BitmapFactory.decodeFile(result.getAbsolutePath(), getBitmapOption(1));
                              imageView.setImageBitmap(bitmap);
                        }
                  } else {
                              Log.e(TAG, "---------文件为null-----------"); 
                  }
           }

           @Override
           protected File doInBackground(String... params) {
                   File b = getImageBitmap(params[0]);
                   return b;
           }
       }

       /** 
        * HttpUrlConnection访问网络 
        * 并下载图片到本地 
        * @param url 
        * @return 
        */
        private File getImageBitmap(String url) {
               URL imgurl = null;
               Bitmap bitmap = null;
               File file = null;
               HttpURLConnection urlConnection;
               try {
                     imgurl = new URL(url);
                     urlConnection = (HttpURLConnection)
                     imgurl.openConnection();
                     urlConnection.setRequestMethod("GET");
                     urlConnection.connect();
                     InputStream is = urlConnection.getInputStream();
               
                     //构建一个file对象用于存储图片
                     file = new File(Environment.getExternalStorageDirectory(), "pic.jpg");
                     fos = new FileOutputStream(file);
                     int len = 0;
                     byte[] buffer = new byte[1024];
        
                     //将输入流写入到我们定义好的文件中
                     while ((len = is.read(buffer)) != -1) {
                              fos.write(buffer, 0, len);
                     }

                    //将缓冲刷入文件
                    fos.flush();
                    is.close();
                    fos.close();
             } catch (IOException e) {
                    e.printStackTrace();
             }                
            return file;
      } 

      /** 
       * 设置Bitmap的Options
       */
      private BitmapFactory.Options getBitmapOption(int inSampleSize) {

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPurgeable = true;
            options.inSampleSize = inSampleSize;
            
            return options;
       }
    


     果然依然能够正常显示

     不要忘记ImageView的adjustViewBounds


     如果我们仅仅只是想显示一下图片, 那么还要先将图片下载,然后将图片文件转化为bitmap, 这样不仅仅会消耗很多用户流量, 而且代码还复杂, 身为程序员, 当然要寻找简单的方式
     我们都知道, 移动端显示的图片都是加载一个图片的网络地址, 如果这样,我们为何不直接使用WebView的特性, 直接加载这个图片地址呢??

方法四.快速解决办法----使用WebView
     直接使用WebView来解决展示超长图片的问题, 轻松

[Java] 纯文本查看 复制代码
        WebView webView = (WebView) findViewById(R.id.webView);
        webView.loadUrl("http://192.168.3.162:8080/gotoclass/test.jpg");

     但是如果仅仅这么做, 图片很有可能会在宽度上出现问题, 所以要让它适应屏幕缩放
[AppleScript] 纯文本查看 复制代码
        
        WebSettings settings = webView.getSettings();
        // 设置可任意缩放
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);
  


2 个回复

倒序浏览
真的很溜写的很好,第二个老师感觉压力山大!!!
回复 使用道具 举报
很666!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马