Android图片加载与缓存开源框架总结七部曲:Glide Picasso ImageLoader Fresco ASimpleCache等

本文主要是介绍Android图片加载与缓存开源框架总结七部曲:Glide Picasso ImageLoader Fresco ASimpleCache等,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

                                                       Android图片加载与缓存开源框架总结

 

 

1)    Picasso      点击下面红色字体进入详解:
picasso-强大的Android图片下载缓存库
2)    Glide         点击下面红色字体进入详解:
Google推荐的图片加载库Glide介绍
3)    Fresco       点击下面红色字体进入详解:
Fresco使用教程
4)    ImageLoader 点击下面红色字体进入详解:
Android UI-开源框架ImageLoader的完美例子

 

 

 

      ImageLoader可以支持图片下载的过程监听,Picasso和Glide都是非常优秀的,而且使用起来非常容易上手,我们站在用户的需求上考虑,若用户要求更完美的展示图片的细节,那么非Picasso莫属,若更注重于顺滑的图片滑动体验Glide更加适合。

 

                    ImageLoader其实也不难,下面来看看代码:

下载地址:

http://download.csdn.net/detail/wwj_748/5975847

http://download.csdn.net/detail/wwj_748/5975847

要使用ImageLoader就要到这里下载jar包:

 

https://github.com/nostra13/Android-Universal-Image-Loader

 

1.功能概要

 Android-Universal-Image-Loader是一个开源的UI组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示。

(1).使用多线程加载图片
(2).灵活配置ImageLoader的基本参数,包括线程数、缓存方式、图片显示选项等;
(3).图片异步加载缓存机制,包括内存缓存及SDCard缓存;
(4).采用监听器监听图片加载过程及相应事件的处理;
(5).配置加载的图片显示选项,比如图片的圆角处理及渐变动画。

2.简单实现

ImageLoader采用单例设计模式,ImageLoader imageLoader = ImageLoader.getInstance();得到该对象,每个ImageLoader采用单例设计模式,ImageLoader必须调用init()方法完成初始化。

  1. //  1.完成ImageLoaderConfiguration的配置  
  2. ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)  
  3.     .memoryCacheExtraOptions(480, 800)          // default = device screen dimensions  
  4.     .discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null)  
  5.     .taskExecutor(...)  
  6.     .taskExecutorForCachedImages(...)  
  7.     .threadPoolSize(3)                          // default  
  8.     .threadPriority(Thread.NORM_PRIORITY - 1)   // default  
  9.     .tasksProcessingOrder(QueueProcessingType.FIFO) // default  
  10.     .denyCacheImageMultipleSizesInMemory()  
  11.     .memoryCache(new LruMemoryCache(2 * 1024 * 1024))  
  12.     .memoryCacheSize(2 * 1024 * 1024)  
  13.     .memoryCacheSizePercentage(13)              // default  
  14.     .discCache(new UnlimitedDiscCache(cacheDir))// default  
  15.     .discCacheSize(50 * 1024 * 1024)        // 缓冲大小  
  16.     .discCacheFileCount(100)                // 缓冲文件数目  
  17.     .discCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default  
  18.     .imageDownloader(new BaseImageDownloader(context)) // default  
  19.     .imageDecoder(new BaseImageDecoder()) // default  
  20.     .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default  
  21.     .writeDebugLogs()  
  22.     .build();  
  23.   
  24. //  2.单例ImageLoader类的初始化  
  25. ImageLoader imageLoader = ImageLoader.getInstance();  
  26. imageLoader.init(config);  
  27.   
  28. //  3.DisplayImageOptions实例对象的配置  
  29. //      以下的设置再调用displayImage()有效,使用loadImage()无效  
  30. DisplayImageOptions options = new DisplayImageOptions.Builder()  
  31.     .showStubImage(R.drawable.ic_stub)          // image在加载过程中,显示的图片  
  32.     .showImageForEmptyUri(R.drawable.ic_empty)  // empty URI时显示的图片  
  33.     .showImageOnFail(R.drawable.ic_error)       // 不是图片文件 显示图片  
  34.     .resetViewBeforeLoading(false)  // default  
  35.     .delayBeforeLoading(1000)  
  36.     .cacheInMemory(false)           // default 不缓存至内存  
  37.     .cacheOnDisc(false)             // default 不缓存至手机SDCard  
  38.     .preProcessor(...)  
  39.     .postProcessor(...)  
  40.     .extraForDownloader(...)  
  41.     .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)// default  
  42.     .bitmapConfig(Bitmap.Config.ARGB_8888)              // default  
  43.     .decodingOptions(...)  
  44.     .displayer(new SimpleBitmapDisplayer()) // default 可以设置动画,比如圆角或者渐变  
  45.     .handler(new Handler())                             // default  
  46.     .build();  
  47.       
  48. //  4图片加载  
  49. //  4.1 调用displayImage  
  50. imageLoader.displayImage(  
  51.     uri,        /* 
  52.                     String imageUri = "http://site.com/image.png";      // from Web 
  53.                     String imageUri = "file:///mnt/sdcard/image.png";   // from SD card 
  54.                     String imageUri = "content://media/external/audio/albumart/13"; // from content provider 
  55.                     String imageUri = "assets://image.png";             // from assets 
  56.                     */  
  57.     imageView,      // 对应的imageView控件  
  58.     options);       // 与之对应的image显示方式选项  
  59.   
  60. //  4.2 调用loadImage  
  61. //      对于部分DisplayImageOptions对象的设置不起作用  
  62. imageLoader.loadImage(  
  63.         uri,   
  64.         options,   
  65.         new MyImageListener()); //ImageLoadingListener  
  66. class MyImageListener extends SimpleImageLoadingListener{  
  67.   
  68.     @Override  
  69.     public void onLoadingStarted(String imageUri, View view) {  
  70.         imageView.setImageResource(R.drawable.loading);  
  71.         super.onLoadingStarted(imageUri, view);  
  72.     }  
  73.   
  74.     @Override  
  75.     public void onLoadingFailed(String imageUri, View view,  
  76.             FailReason failReason) {  
  77.         imageView.setImageResource(R.drawable.no_pic);  
  78.         super.onLoadingFailed(imageUri, view, failReason);  
  79.     }  
  80.   
  81.     @Override  
  82.     public void onLoadingComplete(String imageUri, View view,  
  83.             Bitmap loadedImage) {  
  84.         imageView.setImageBitmap(loadedImage);  
  85.         super.onLoadingComplete(imageUri, view, loadedImage);  
  86.     }  
  87.   
  88.     @Override  
  89.     public void onLoadingCancelled(String imageUri, View view) {  
  90.         imageView.setImageResource(R.drawable.cancel);  
  91.         super.onLoadingCancelled(imageUri, view);  
  92.     }  
  93.       
  94. }  

3.支持的Uri

  1. String imageUri = "http://site.com/image.png";      // from Web  
  2. String imageUri = "file:///mnt/sdcard/image.png";   // from SD card  
  3. String imageUri = "content://media/external/audio/albumart/13"; // from content provider  
  4. String imageUri = "assets://image.png";             // from assets  
  5. String imageUri = "drawable://" + R.drawable.image; // from drawables (only images, non-9patch)  

 

加载drawables下图片,可以通过ImageView.setImageResource(...) 而不是通过上面的ImageLoader.

4.缓冲至手机

默认不能保存缓存,必须通过下面的方式指定

  1. DisplayImageOptions options = new DisplayImageOptions.Builder()  
  2.         ...  
  3.         .cacheInMemory(true)  
  4.         .cacheOnDisc(true)  
  5.         ...  
  6.         .build();  
  7. ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())  
  8.         ...  
  9.         .defaultDisplayImageOptions(options)  
  10.         ...  
  11.         .build();  
  12. ImageLoader.getInstance().init(config); // Do it on Application start  
  13.   
  14. ImageLoader.getInstance().displayImage(imageUrl, imageView);    /* 
  15.                                             默认为defaultDisplayImageOptions设定的options对象,此处不用指定options对象 */  

或者通过下面这种方式

  1. DisplayImageOptions options = new DisplayImageOptions.Builder()  
  2.         ...  
  3.         .cacheInMemory(true)  
  4.         .cacheOnDisc(true)  
  5.         ...  
  6.         .build();  
  7. ImageLoader.getInstance().displayImage(imageUrl, imageView, options); //此处指定options对象  

由于缓存需要在外设中写入数据,故需要添加下面的权限

  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

5.OutOfMemoryError

如果OutOfMemoryError错误很常见,可以通过下面的方式设置
(1).减少configuration中线程池的线程数目(.threadPoolSize(...)) 推荐为1 - 5
(2).display options通过.bitmapConfig(Bitmap.Config.RGB_565)设置. Bitmaps in RGB_565 consume 2 times less memory than in ARGB_8888.
(3).使用configuration的memoryCache(new WeakMemoryCache())方法 或者不调用.cacheInMemory()方法
(4).display options通过.imageScaleType(ImageScaleType.IN_SAMPLE_INT) 或者 .imageScaleType(ImageScaleType.EXACTLY)方法
(4).避免使用RoundedBitmapDisplayer,它创建了一个新的ARGB_8888 Bitmap对象

6.内存缓存管理

通过imageLoaderConfiguration.memoryCache([new LruMemoryCache(1)]))对手机内存缓存进行管理

LruMemoryCache

API >= 9默认.it is moved to the head of a queue.

FreqLimitedMemoryCache

当超过缓存大小后,删除最近频繁使用的bitmap

LRULimitedMemoryCache

API < 9 默认.当超过缓存大小后,删除最近使用的bitmap

FIFOLimitedMemoryCache

FIFO rule is used for deletion when cache size limit is exceeded

LargestLimitedMemoryCache

The largest bitmap is deleted when cache size limit is exceeded

WeakMemoryCache

Unlimited cache

7.SDcard缓存管理

通过imageLoaderConfiguration.discCache([new TotalSizeLimitedDiscCache()]))对SD卡缓存进行管理

UnlimitedDiscCache

default The fastest cache, doesn't limit cache size

TotalSizeLimitedDiscCache

Cache limited by total cache size. If cache size exceeds specified limit then file with themost oldest lastusage date will be deleted

FileCountLimitedDiscCache

Cache limited by file count. If file count in cache directory exceeds specified limit then file with the most oldest last usage date will be deleted.

LimitedAgeDiscCache

Size-unlimited cache with limited files' lifetime. If age of cached file exceeds defined limit then it will be deleted from cache.

UnlimitedDiscCache is 30%-faster than other limited disc cache implementations.

 

 

 

?

 

Glide是谷歌推荐使用的加载图片的框架,它相对于其他的框架有更多的有点,说到Glide我们不得不谈谈Picasso,为什么呢?这是因为Picasso的使用与Glide的使用上非常的相似,但是细细看,有明显不同,首先我们看下Picasso与Glide的基本用法?


Picasso:            


   Picasso.with(this)
                 .load(url)//加载图片
                 .placeholder(R.mipmap.ic_launcher)//正在加载时的图片
                 .error(R.mipmap.ic_launcher)//加载错误是的图片
                 .into(glide_image2);
Glide:


  Glide.with(this)
                 .load(url)//加载图片
               .placeholder(R.mipmap.ic_launcher)//正在加载时的图片
                 .error(R.mipmap.ic_launcher)//加载错误是的图片
                 .into(glide_image);
1、看到没有,是不是一样呢,基本上它们的用法一直,但是我们在使用Glide时需要注意,Glide.with(this),我们在传入的时候,我建议传入Actitiy,Fragment对应得context,而不是全局的context,为什么呢,这是因为这样我们可以让Gilde加载图片与我们的Activity,Fragment的生命周期一直,创建时去加载,销毁时停止加载,


2、Glide的加载速度比Picasso的加载速度要快,但是消耗的内存要比Picasso的内存高,为什么呢这是因为Gilde他是根据你传入的尺寸进行缓存,如果俩个地方需要      全尺寸缓存,另一个地方按照比例缓存,那么Glide需要缓存俩次,而Picsso是全尺寸的缓存,每当重新加载时,需要重新绘制


   /**
       * Glide的全尺寸缓存
       */
      public void GlideImage3(String url) {
          Glide.with(this)
                  .load(url)//加载图片
                  .placeholder(R.mipmap.ic_launcher)//正在加载时的图片
                  .error(R.mipmap.ic_launcher)//加载错误是的图片
                  .diskCacheStrategy(DiskCacheStrategy.ALL)
                 .into(glide_image);
     }
 

3,Picasso加载的bitmap格式ARGB_8888而Glide所加载的bitmap格式ARGB_565当然我们可以通过实现GlideMenu来实现

  /**
   * 更改Glide的bitmap的格式为ARGB_8888
   * Created by joe.xiang on 2016/6/9.
   */
 public class GlideConfigration implements GlideModule {
  
  
      @Override
      public void applyOptions(Context context, GlideBuilder builder) {
         builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
     }
 
     @Override
     public void registerComponents(Context context, Glide glide) {
 
     }
 }

 

4、Glide的setTag方法不同之处?


   我们可以通过在我们的values下建立一个ids的xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="image_tag" type="id"/>
</resources>
通过Image.setTag(R.id.image_tag,url)的形式来进行设置

5、Glide如何设置圆形图片


    对于如何制作圆形的方法,有很多可以通过自定义ImageView,当然Glide也给我们提供了很多的方法来时圆角图片。一般有一下方法


    1、自定一个Transform 继承 BitmapTransformation




  /**
   * Created by joe.xiang on 2016/6/9.
   */
  public  class CircleTransform extends BitmapTransformation {
  
      public CircleTransform(Context context) {
         super(context);
      }
 
    @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
         return circleCrop(pool, toTransform);
     }
 
     private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
         if (source == null) return null;
         int size = Math.min(source.getWidth(), source.getHeight());
         int x = (source.getWidth() - size) / 2;
         int y = (source.getHeight() - size) / 2;
 
         // TODO this could be acquired from the pool too
         Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
         Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
         if (result == null) {
             result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
         }
         Canvas canvas = new Canvas(result);
         Paint paint = new Paint();
         paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
         paint.setAntiAlias(true);
         float r = size / 2f;
         canvas.drawCircle(r, r, r, paint);
        return result;
     }
 
     @Override public String getId() {
         return getClass().getName();
     }
 }




    /**
       * 通过Glide的TransForMation 自定义圆形图片的bitmap
       */
      public void RoundImage(String url) {
          Glide.with(this)
                  .load(url)
                  .asBitmap()
                  .transform(new CircleTransform(this))
                  .into(glide_image5);
     }


 2、我们可以通过BitmapImageVieTarget,来得到一个带圆角的RoundBitmapDrawable;


   /**
       * 通过RoundBitmapDrawable
       */
      public void RoundImage2(String url) {
          Glide.with(this)
                  .load(url)
                  .asBitmap()
                  .into(new BitmapImageViewTarget(glide_image6) {
                     @Override
                     protected void setResource(Bitmap resource) {
                        RoundedBitmapDrawable RoundedBitmapDrawable = RoundedBitmapDrawableFactory.create(Glide_1.this.getResources(), resource);
                        RoundedBitmapDrawable.setCircular(true);
                         glide_image6.setImageDrawable(RoundedBitmapDrawable);
                    }
               });


3、我们可以通过自定义RoundedCornerLayout 继承RelavityLayout来实现圆角图片效果


  **
   * Created by joe.xiang on 2016/6/9.
   */
  public class RoundedCornerLayout  extends RelativeLayout {
      private Bitmap maskBitmap;
      private Paint paint;
      private float cornerRadius;
  
     public RoundedCornerLayout(Context context) {
         super(context);
         init(context, null, 0);
     }
     public RoundedCornerLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         init(context, attrs, 0);
    }
 
     public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         init(context, attrs, defStyle);
     }
 
    private void init(Context context, AttributeSet attrs, int defStyle) {
         paint = new Paint(Paint.ANTI_ALIAS_FLAG);
         setWillNotDraw(false);
    }


     @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
 
         if (maskBitmap == null) {
            // This corner radius assumes the image width == height and you want it to be circular
             // Otherwise, customize the radius as needed
             cornerRadius = canvas.getWidth() / 2;
             maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
         }
 
         canvas.drawBitmap(maskBitmap, 0f, 0f, paint);
     }


     private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
         Canvas canvas = new Canvas(mask);
 
         Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
         paint.setColor(Color.WHITE); // TODO set your background color as needed
 
         canvas.drawRect(0, 0, width, height, paint);
 
         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
         canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);
         return mask;
     }
 }




    <huanxin.exmaple.com.android_glidedemo.RoundedCornerLayout
                     android:layout_width="200dp"
                     android:layout_height="200dp">
                        <ImageView
                             android:id="@+id/glide_image7"
                             android:layout_width="200dp"
                            android:layout_height="200dp"
                            android:scaleType="centerCrop"
                            />
  </huanxin.exmaple.com.android_glidedemo.RoundedCornerLayout>


使用上跟一般使用没什么区别。。。。。


4 、当然我们亦可以使用开源的圆角图片的自定义控件?




   Glide.with(this).load(url).into(new SimpleTarget<GlideDrawable>() {
              @Override
              public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                  //使用自定义的圆角图片
              }
          });


对于Glide加载图片还有很多可以去研究的地方,它还可以加载gif的动态图,不过这个方法要谨慎使用,因为这个非常耗内存,对于Glide的使用花了一个下午对于他的一些基本使用就总结导致,过段时间深入研究后在总结了、一下附上加载的图片效果图。

 

                                                                                 Android Glide

 

 

Android Glide是一个开源的图片加载和缓存处理的第三方框架。和Android的Picasso库类似,个人感觉比Android Picasso好用。Android Glide使自身内部已经实现了缓存策略,使得开发者摆脱Android图片加载的琐碎事务,专注逻辑业务的代码。Android Glide使用便利,短短几行简单明晰的代码,即可完成大多数图片从网络(或者本地)加载、显示的功能需求。

使用Android Glide,需要先下载Android Glide的库,Android Glide在github上的项目主页:

https://github.com/bumptech/glide 。

实际的项目使用只需要到Glide的releases页面把jar包下载后导入到本地的libs里面即可直接使用。Glide的releases的页面地址:https://github.com/bumptech/glide/releases ,在此页面找到最新的jar包,下载后放到自己项目的libs中,比如glide 3.6.0库的jar包下载地址:https://github.com/bumptech/glide/releases/download/v3.6.0/glide-3.6.0.jar


接下来是在自己的项目中具体使用,现在给出一个具体的使用例子加以简单说明(通过网络加载图片然后在ImageView中显示出来):

MainActivity.java

 下载地址:

http://download.csdn.net/detail/shenggaofei/9613805

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import com.bumptech.glide.Glide;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
     private Activity mActivity;
     // 将从此URL加载网络图片。
     private String img_url = "https://avatar.csdn.net/9/7/A/1_zhangphil.jpg" ;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         mActivity = this ;
         setContentView(R.layout.activity_main);
         ListView lv = (ListView) findViewById(R.id.listView);
         lv.setAdapter( new MyAdapter( this , R.layout.item));
     }
     private class MyAdapter extends ArrayAdapter {
         private int resource;
         public MyAdapter(Context context, int resource) {
             super (context, resource);
             this .resource = resource;
         }
         @Override
         public View getView( int position, View convertView, ViewGroup parent) {
             if (convertView == null ) {
                 convertView = LayoutInflater.from(mActivity).inflate(resource,
                         null );
             }
             ImageView iv = (ImageView) convertView.findViewById(R.id.imageView);
             Glide.with(mActivity).load(img_url).centerCrop()
             /*
              * 缺省的占位图片,一般可以设置成一个加载中的进度GIF图
              */
             .placeholder(R.drawable.loading).crossFade().into(iv);
             return convertView;
         }
         @Override
         public int getCount() {
             // 假设加载的数据量很大
             return 10000 ;
         }
     }
}

 

 

 

MainActivity.java需要的两个布局文件:

activity_main.xml

 

?
1
2
3
4
5
6
<linearlayout android:layout_height= "match_parent" android:layout_width= "match_parent" android:orientation= "vertical" xmlns:android= "http://schemas.android.com/apk/res/android" >
     <listview android:id= "@+id/listView" android:layout_height= "wrap_content" android:layout_width= "match_parent" >
     </listview>
</linearlayout>

 

 

 

 

item.xml

 

?
1
2
3
4
5
6
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<linearlayout android:layout_height= "match_parent" android:layout_width= "match_parent" android:orientation= "vertical" xmlns:android= "http://schemas.android.com/apk/res/android" >
     <imageview android:id= "@+id/imageView" android:layout_height= "wrap_content" android:layout_width= "wrap_content" >
</imageview></linearlayout>

                                                                     

 

                                                               

Android Picasso加载网络图片等比例缩放

 

下载地址:

http://download.csdn.net/my

在做Android图片加载的时候,由于手机屏幕受限,很多大图加载过来的时候,我们要求等比例缩放,比如按照固定的宽度,等比例缩放高度,使得图片的尺寸比例得到相应的缩放,但图片没有变形。显然按照android:scaleType不能实现,因为会有很多限制,所以必须要自己写算法。 
之前也写过一篇文章Android根据屏幕宽度缩放图片,但这是缩放的本地图片,网络图片该如何办呢?

通过Picasso来缩放 
其实picasso提供了这样的方法。具体是显示Transformation 的transform方法。 
1、先获取网络或本地图片的宽高 
2、获取需要的目标宽 
3、按比例得到目标的高度 
4、按照目标的宽高创建新图

<code class="hljs mel has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span style="font-size:18px;">Transformation transformation = new Transformation() {<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@Override</span>public Bitmap transform(Bitmap <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>) {<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> targetWidth = mImg.getWidth();LogCat.i(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"source.getHeight()="</span>+<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.getHeight()+<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">",source.getWidth()="</span>+<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.getWidth()+<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">",targetWidth="</span>+targetWidth);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.getWidth()==<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>;}<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果图片小于设置的宽度,则返回原图</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.getWidth()<targetWidth){<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>{<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果图片大小大于等于设置的宽度,则按照设置的宽度比例来缩放</span>double aspectRatio = (double) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.getHeight() / (double) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.getWidth();<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> targetHeight = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) (targetWidth * aspectRatio);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (targetHeight != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> && targetWidth != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {Bitmap result = Bitmap.createScaledBitmap(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>, targetWidth, targetHeight, false);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (result != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>) {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// Same bitmap is returned if sizes are the same</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>.recycle();}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> result;} <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">source</span>;}}}<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">@Override</span>public String key() {<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"transformation"</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" desiredWidth"</span>;}};</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">1</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">2</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">3</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">4</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">5</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">6</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">7</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">8</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">9</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">10</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">11</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">12</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">13</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">14</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">15</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">16</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">17</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">18</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">19</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">20</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">21</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">22</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">23</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">24</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">25</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">26</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">27</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">28</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">29</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">30</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">31</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">32</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">33</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">34</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">35</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">36</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">37</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">38</span></li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">1</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">2</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">3</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">4</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">5</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">6</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">7</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">8</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">9</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">10</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">11</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">12</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">13</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">14</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">15</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">16</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">17</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">18</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">19</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">20</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">21</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">22</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">23</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">24</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">25</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">26</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">27</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">28</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">29</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">30</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">31</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">32</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">33</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">34</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">35</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">36</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">37</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">38</span></li></ul>

之后在Picasso设置transform

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span style="font-size:18px;">            Picasso<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.with</span>(mContext)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.load</span>(imageUrl)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.placeholder</span>(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.mipmap</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zhanwei</span>)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.error</span>(R<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.mipmap</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.zhanwei</span>)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.transform</span>(transformation)<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.into</span>(viewHolder<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.mImageView</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">1</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">2</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">3</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">4</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">5</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">6</span></li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">1</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">2</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">3</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">4</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">5</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-size:18px;">6</span></li></ul>

参考文献: 
http://stackoverflow.com/questions/21889735/resize-image-to-full-width-and-variable-height-with-picasso 
http://blog.csdn.net/larryl2003/article/details/6919513

                                  

                                                              

                                          ASimpleCache缓存框架的使用

 简述

简述为ASimpleCache官网( 点击打开链接)对其介绍,ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。

0.1ASimpleCache可以缓存什么

普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据。

0.2ASimpleCache有什么特色

(1)轻:轻到只有一个JAVA文件;
(2)可配置:可以配置缓存路径,缓存大小,缓存数量等;
(3)可以设置缓存超时时间,缓存超时自动失效,并被删除;
(4)支持多进程。

0.3ASimpleCache在Android中的使用场景

(1)替换SharePreference当做配置文件;
(2)可以缓存网络请求数据,可以作为app数据(字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 byte数据)的缓存工具;
(3)可以作为预加载数据的缓存库;

1ASimpleCache的使用

ASimpleCache使用起来太简单了,尤其是使用过SharePreference。

1.1缓存字符串

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. //缓存  
  2. private ACache mACache;  
  3.   
  4. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. mACache.put(Constants.KEY_STRING, result);  
还有,获取缓存数据:
[java]  view plain  copy
  1. String result = mACache.getAsString(Constants.KEY_STRING);  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_STRING);  

1.2缓存JsonObject

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. //缓存  
  2. private ACache mACache;  
  3.   
  4. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. mACache.put(Constants.KEY_JSONOBJECT, jsonObject);  
还有,获取缓存数据:
[java]  view plain  copy
  1. JSONObject result = mACache.getAsJSONObject(Constants.KEY_JSONOBJECT);  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_JSONOBJECT);  

1.3缓存JsonArray

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. //缓存  
  2. private ACache mACache;  
  3.   
  4. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. mACache.put(Constants.KEY_JSONARRAY, jsonArray);  
还有,获取缓存数据:
[java]  view plain  copy
  1. JSONArray result = mACache.getAsJSONArray(Constants.KEY_JSONARRAY);  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_JSONARRAY);  

1.4缓存Bitmap

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. //缓存  
  2. private ACache mACache;  
  3.   
  4. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);  
  2.         mACache.put(Constants.KEY_BITMAP, bitmap);  
还有,获取缓存数据:
[java]  view plain  copy
  1. Bitmap bitmap = mACache.getAsBitmap(Constants.KEY_BITMAP);  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_BITMAP);  

1.5缓存Drawable

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. //缓存  
  2. private ACache mACache;  
  3.   
  4. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher);  
  2.         mACache.put(Constants.KEY_DRAWABLE, drawable);  
还有,获取缓存数据:
[java]  view plain  copy
  1. Drawable bitmap = mACache.getAsDrawable(Constants.KEY_DRAWABLE);  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_DRAWABLE);  

1.6缓存序列化的java对象

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. //缓存  
  2. private ACache mACache;  
  3.   
  4. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. mACache.put(Constants.KEY_JAVA_BEAN, mWeather);  
还有,获取缓存数据:
[java]  view plain  copy
  1. Weather result = (Weather) mACache.getAsObject(Constants.KEY_JAVA_BEAN);  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_JAVA_BEAN);  

1.7缓存byte数据

首先,创建ASimpleCache对象:
[java]  view plain  copy
  1. private ACache mACache;  
  2.   
  3. mACache = ACache.get(this);  
其次,存储数据:
[java]  view plain  copy
  1. private void saveByte() {  
  2.         OutputStream ostream = null;  
  3.         try {  
  4.             ostream = mACache.put(Constants.KEY_BYTE);  
  5.         } catch (FileNotFoundException e) {  
  6.             e.printStackTrace();  
  7.         }  
  8.         if (ostream == null) {  
  9.             ToastUtil.simpleToast(this"Open stream error!");  
  10.             return;  
  11.         }  
  12.         try {  
  13.             URL u = new URL(Constants.downloadUrl);  
  14.             HttpURLConnection conn = (HttpURLConnection) u.openConnection();  
  15.             conn.connect();  
  16.             InputStream stream = conn.getInputStream();  
  17.             byte[] buff = new byte[1024];  
  18.             int counter;  
  19.             while ((counter = stream.read(buff)) > 0) {  
  20.                 ostream.write(buff, 0, counter);  
  21.             }  
  22.         } catch (IOException e) {  
  23.             e.printStackTrace();  
  24.         } finally {  
  25.             try {  
  26.                 // cache update  
  27.                 ostream.close();  
  28.             } catch (IOException e) {  
  29.                 e.printStackTrace();  
  30.             }  
  31.             runOnUiThread(new Runnable() {  
  32.                 @Override  
  33.                 public void run() {  
  34.                     showTv.setText("done...");  
  35.                 }  
  36.             });  
  37.         }  
  38.     }  
还有,获取缓存数据:
[java]  view plain  copy
  1. private void getsByte() {  
  2.         InputStream stream = null;  
  3.         try {  
  4.             stream = mACache.get(Constants.KEY_BYTE);  
  5.         } catch (FileNotFoundException e) {  
  6.             e.printStackTrace();  
  7.         }  
  8.         if (stream == null) {  
  9.             ToastUtil.simpleToast(this"Bitmap cache is null ...");  
  10.             showTv.setText("file not found");  
  11.             return;  
  12.         }  
  13.         try {  
  14.             showTv.setText("file size: " + stream.available());  
  15.         } catch (IOException e) {  
  16.             showTv.setText("error " + e.getMessage());  
  17.         }  
  18.     }  
最后,清除缓存:
[java]  view plain  copy
  1. mACache.remove(Constants.KEY_BYTE);  

 

觉得不错的话,记得打赏一下:

https://blog.csdn.net/shenggaofei/article/details/105873568

这篇关于Android图片加载与缓存开源框架总结七部曲:Glide Picasso ImageLoader Fresco ASimpleCache等的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/432184

相关文章

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

Java 缓存框架 Caffeine 应用场景解析

《Java缓存框架Caffeine应用场景解析》文章介绍Caffeine作为高性能Java本地缓存框架,基于W-TinyLFU算法,支持异步加载、灵活过期策略、内存安全机制及统计监控,重点解析其... 目录一、Caffeine 简介1. 框架概述1.1 Caffeine的核心优势二、Caffeine 基础2

Redis高性能Key-Value存储与缓存利器常见解决方案

《Redis高性能Key-Value存储与缓存利器常见解决方案》Redis是高性能内存Key-Value存储系统,支持丰富数据类型与持久化方案(RDB/AOF),本文给大家介绍Redis高性能Key-... 目录Redis:高性能Key-Value存储与缓存利器什么是Redis?为什么选择Redis?Red

React 记忆缓存的三种方法实现

《React记忆缓存的三种方法实现》本文主要介绍了React记忆缓存的三种方法实现,包含React.memo、useMemo、useCallback,用于避免不必要的组件重渲染和计算,感兴趣的可以... 目录1. React.memo2. useMemo3. useCallback使用场景与注意事项在 Re

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码