• 简介
  • 下载
  • 配置
  • 使用
    • 简单使用
    • 高级用法
      • RequestOptions
      • TransitionOptions
      • Generated API
      • RequestBuilder
      • Configuration
    • 使用技巧
      • Glide的图片变换Transformations
      • Glide的过渡动画Transitions
      • Glide的缓存管理Caching

简介

Glide项目于2012年12月21日由Google工程师Sam sjudd首次提交,到现在已经迭代了四个大的版本,受到了越来越多开发者的欢迎,Star数也已接近两万。Glide v4.x相对于之前比较稳定的Glide v3.7.0来说,有了很大的变化,一个比较大的改动就是Glide处理加载选项(如裁剪变换、占位符、缓存策略等)的方式。在之前的Glide v3中,加载选项由一系列复杂的builder处理,而Glide v4中这些已经被单一类型的builder所取代,且提供了一系列可供builder使用的选项对象(options objects)。

下载

在build.gradle中添加依赖:

    compile 'com.github.bumptech.glide:glide:4.3.0'annotationProcessor 'com.github.bumptech.glide:compiler:4.3.0'

Glide需要support库的支持,如果你的项目还没有依赖support库,还需要添加support-v4依赖:

    compile 'com.android.support:support-v4:26.1.0'

配置

如果你使用了proguard混淆,可能需要添加如下混淆规则:

    -keep public class * implements com.bumptech.glide.module.GlideModule-keep public class * extends com.bumptech.glide.AppGlideModule-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {**[] $VALUES;public *;}

你还需要声明联网、磁盘读写权限:

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

使用

简单使用

很多情况下,使用Glide加载图片只需要一行代码

Glide.with(fragment).load(myUrl).into(imageView);

取消加载也一样简单:

Glide.with(fragment).clear(imageView);

虽然清理资源加载是个很好的做法,不过很多情况下你没有必要这样做,因为Glide会根据你在with()方法中传入的Activity/Fragment的生命周期决定资源的加载和清理。

高级用法

RequestOptions

Glide中很多选项设置都可以通过RequestOptions类和apply()方法完成,包括:

  • 占位符(Placeholders)
  • 图片变换(Transformations)
  • 缓存策略(Caching Strategies)
  • 编码质量、解码配置等组件选项(Component specific options)
    RequestOptions requestOptions = new RequestOptions().placeholder(R.drawable.default_avatar).circleCrop().diskCacheStrategy(DiskCacheStrategy.ALL).encodeQuality(90);Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").apply(requestOptions).into(imageView);

placeholder

请求过程中显示,请求完成后被替换为请求到的资源。如果请求的资源是内存中的,placeholder可能就不会被显示。
如果请求失败且error Drawable没有设置,placeholder将继续被显示。
如果请求的url/model为空且error Drawable和fallback Drawable都没设置,placeholder将继续被显示。
error
当请求永远失败时显示error Drawable。
当请求的url/model为空且fallback Drawable没设置时显示error Drawable
fallback
当请求的url/model为空时显示fallback Drawable。
fallback Drawable主要目的是允许用户表明"空"是否被允许,因为Glide默认把空的url/model当做error处理。一个典型的场景就是未设置头像用户的avatar字段可能是 null,而显示的时候我们需要显示一个默认的用户头像,此时设置fallback是个很好地选择。
thumbnail请求
缩略图请求像普通的全尺寸请求一样是一个完整的资源请求,如果缩略图请求在完整请求完成之前完成,就加载并展示缩略图请求请求到的资源。
缩略图由于比全尺寸图更小所以加载的更快,不过无法保证两个请求完成的顺序。
但是,如果缩略图请求在全尺寸请求之后完成,缩略图资源并不会替换全尺寸资源。
error请求
从Glide v4.3.0开始,当你的主请求失败时,你可以通过 error() API指定一个 RequestBuilder去开始一个新的请求。也就是说你可以指定一个备用请求,如果主请求成功完成那么你的error RequestBuilder将不会开始执行。如果你同时指定了 thumbnail()请求和 error()请求,一旦主请求失败 error()请求就开始执行,即使 thumbnail()请求成功了。

TransitionOptions

Glide可以通过TransitionOptions设置请求完成后的显示行为,如:

  • 淡入效果(View fade in)
  • 交叉渐入渐出(Cross fade from the placeholder)
  • 无过渡效果(No transition)
    RequestOptions requestOptions = new RequestOptions().placeholder(R.drawable.default_avatar).circleCrop();DrawableTransitionOptions transitionOptions = new DrawableTransitionOptions().crossFade();Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").apply(requestOptions).transition(transitionOptions).into(imageView);

如果不设置过渡效果,当图片加载完之后就会立刻替换之前的图片。为了避免这样突然的改变,让图片更平滑地展示,我们可以通过TransitionOptions添加过渡效果。不过Transitions只面对单个请求的上下文,所以你不能通过Transitions定义一个请求到另一个请求的过渡动画。
Glide v4默认不应用任何的过渡动画,如果需要必须手动为每个请求应用过渡动画。
Glide要加载的图片资源可能来自:

  • Glide的内存缓存(memory cache)
  • Glide的磁盘缓存(disk cache)
  • 本地的File或Uri源
  • 远程的Url或Uri源

如果加载的图片资源来自Glide的内存缓存,加载过程特别快,Glide的内置transitions将不会应用,其它情况Glide的内置transitions才会应用。

RequestOptions不同,TransitionOptions与Glide要加载的资源类型直接关联(TranscodeType),也就是说,如果你请求一个Bitmap,你需要使用BitmapTransitionOptions而不是DrawableTransitionOptions

Generated API

可能你已经注意到了,像RequestOptionsTransitionOptions这些options虽然将选项设置清晰地隔离开来,但额外地去创建这些对象会影响流式编程的风格,我们更希望能够连贯地调用方法,类似这样:

GlideApp.with(fragment).load(myUrl).placeholder(placeholder).circleCrop().diskCacheStrategy(DiskCacheStrategy.ALL).transition(withCrossFade()).into(imageView);

所以,Glide v4使用annotation processor自动生成一个API,以便应用可以流式地使用包括RequestBuilder, RequestOptions在内的所有options。
Generated API有两个目的:

  • 一些集成库可以继承Glide的API去自定义一些options
  • 应用也可以继承Glide的API去添加一些绑定通用options的方法

要使用Generated API也很简单,只需要在应用中写一个AppGlideModule的实现即可:

package com.example.myapp;import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

编译一下(Rebuild Project),apt就会在相同包名下生成包含GlideApp在内的一系列文件 ,使用GlideApp你就可以流式地使用所有options的方法了。

RequestBuilder

每次调用Glide.with()你都会得到一个RequestBuilder, 而RequestBuilder就是Glide请求的主干,负责把你的options和请求的url/model结合起来并开始新的加载。
RequestBuilder可以指定:

  • 你想要加载的资源类型(Bitmap, Drawable等)
  • 你想要加载的资源的url/model
  • 你想要加载资源的view
  • 你想要应用的RequestOption对象
  • 你想要应用的TransitionOption对象
  • 你想要加载的thumbnail()缩略图

RequestBuilder与你想要加载的资源类型直接关联(TranscodeType),默认返回RequestBuilder<Drawable>,你可以通过as...方法改变: RequestBuilder<Bitmap> requestBuilder = Glide.with(fragment).asBitmap();RequestBuilder可以被重用去开始多个加载:

RequestBuilder<Drawable> requestBuilder =Glide.with(fragment).asDrawable().apply(requestOptions);for (int i = 0; i < numViews; i++) {ImageView view = viewGroup.getChildAt(i);String url = urls.get(i);requestBuilder.load(url).into(view);
}

Configuration

Glide v4中有两个类可以配置Glide: AppGlideModuleLibraryGlideModule,这两个类都可以注册ModelLoader, ResourceDecoder等额外组件,但只有AppGlideModule允许更改包括缓存位置、大小在内的应用特定设置。
一个应用只能有一个AppGlideModule实现(如果有多个编译时就会报错),所以libraries是不能提供AppGlideModule的实现的。
为了让Glide更好地寻找AppGlideModuleLibraryGlideModule实现,它们的实现类必须用@GlideModule注解,有了这个注解,Glide的annotation processor就可以在编译时找到所有的实现类了。
如果libraries想配置Glide,必须:

  • 添加一到多个LibraryGlideModule实现
  • 每个LibraryGlideModule都添加@GlideModule注解
  • 添加Glide的annotation processor依赖
@GlideModule
public final class OkHttpLibraryGlideModule extends LibraryGlideModule {@Overridepublic void registerComponents(Context context, Glide glide, Registry registry) {registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());}
}
compile 'com.github.bumptech.glide:annotations:4.2.0'

如果应用想配置Glide,必须有且只有一个AppGlideModule实现,且混淆时不能混淆这些实现。
Glide默认内存缓存使用LruResourceCache(MemoryCache接口的实现),内存缓存的大小由MemorySizeCalculator决定,而MemorySizeCalculator会根据设备的RAM大小和屏幕分辨率决定内存缓存的大小。 你可以自定义缓存实现或缓存大小,如

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mbbuilder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));}
}

Glide默认磁盘缓存使用DiskLruCacheWrapper,磁盘缓存默认大小是250 MB,默认路径是/data/data/your.application.package/cache/image_manager_disk_cache,这个路径是应用内部缓存路径,如果你想要缓存到外部公共目录下,可以这样设置:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {builder.setDiskCache(new ExternalDiskCacheFactory(context));}
}

也可以指定内部/外部磁盘缓存大小、缓存路径:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {int diskCacheSizeBytes = 1024 * 1024 * 100; // 100 MBbuilder.setDiskCache(new InternalDiskCacheFactory(context, "cacheFolderName", diskCacheSizeBytes));}
}

甚至可以自定义磁盘缓存的实现:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {builder.setDiskCache(new DiskCache.Factory() {@Overridepublic DiskCache build() {return new YourAppCustomDiskCache();}});}
}

利用AppGlideModule,你可以为所有请求应用默认的RequestOptions:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {builder.setDefaultRequestOptions(new RequestOptions().format(DecodeFormat.RGB_565).disallowHardwareBitmaps());}
}

你也可以使用RequestManagerapplyDefaultRequestOptions方法为某个Activity/Fragment应用默认的RequestOptions:

Glide.with(fragment).applyDefaultRequestOptions(new RequestOptions().format(DecodeFormat.RGB_565).disallowHardwareBitmaps());

虽然RequestManager也有setDefaultRequestOptions方法来完全替换之前默认RequestOptions(通过AppGlideModuleRequestManager设置的),但是为了不影响一些默认选项,使用applyDefaultRequestOptions更安全。
当加载bitmap出错(如OOM)时,Glide默认只会打印log,你可以使用GlideExecutor.UncaughtThrowableStrategy指定出错时的策略:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {final UncaughtThrowableStrategy myUncaughtThrowableStrategy = new ...builder.setDiskCacheExecutor(newDiskCacheExecutor(myUncaughtThrowableStrategy));builder.setResizeExecutor(newSourceExecutor(myUncaughtThrowableStrategy));}
}

为了方便调试,你可以修改Glide的Log level:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void applyOptions(Context context, GlideBuilder builder) {builder.setLogLevel(Log.DEBUG);}
}

应用和Libraries都可以注册一些Glide components,包括:

  • ModelLoader,用于加载自定义的Model (Urls, Uris, POJOs)和Data (InputStreams, FileDescriptors).
  • ResourceDecoder,用于解码Resources (Drawables, Bitmaps)或Data (InputStreams, FileDescriptors).
  • Encoder,用于把Data (InputStreams, FileDescriptors)写入Glide磁盘缓存.
  • ResourceTranscoder,用于把Resources (BitmapResource)转成其他类型的Resources (DrawableResource).
  • ResourceEncoder,用于把Resources (BitmapResource, DrawableResource)写入Glide磁盘缓存.

注册components的过程也很简单,只需要在AppGlideModuleLibraryGlideModuleregisterComponents()方法中使用Registry注册即可:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void registerComponents(Context context, Glide glide, Registry registry) {registry.append(Photo.class, InputStream.class, new CustomModelLoader.Factory());}
}

资源的加载过程:
一系列已注册的components(包括Glide默认已注册的和Modules中注册的)定义了一系列的加载路径(load paths),每个加载路径都是从load()方法提供的Model到as()方法指定的Resource类型的一步步处理,一个加载路径包含以下几个步骤:
1. Model -> Data (ModelLoader负责)
2. Data -> Resource (ResourceDecoder负责)
3. Resource -> Transcoded Resource (可选,ResourceTranscoder负责).
Encoder可以在第2步之前把Data (InputStreams, FileDescriptors)写入Glide磁盘缓存,ResourceEncoder可以在第3步之前把Resources (BitmapResource, DrawableResource)写入Glide磁盘缓存。
当一个请求开始后,Glide将尝试所有从Model到请求的Resource类型的可用路径。如果任何一个加载路径成功,这个请求就将成功。只有所有可用加载路径都失败时,这个请求才会失败。

关于Components的顺序:
在加载的过程中,Glide将尝试每个已注册的ModelLoaderResourceDecoder。而尝试的顺序,你可以通过Registryprepend(), append(), 和replace()方法设置。
1.prepend()将确保你的ModelLoaderResourceDecoder先于所有之前注册的components调用,所以当需要处理已存在的Model/Data子集时,你需要使用prepend()方法。如果你的ModelLoaderResourceDecoderhandles()方法返回false或者失败时, 所有其它的ModelLoaderResourceDecoder将按其注册顺序被逐个调用。如当你需要自己处理某一类String类型url的加载时,你应该使用prepend()方法以便你自定义的ModelLoader(继承BaseGlideUrlLoader<String>)先于Glide默认String类型url的ModelLoader被调用:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void registerComponents(Context context, Glide glide, Registry registry) {registry.prepend(String.class, InputStream.class, new CustomUrlModelLoader.Factory());}
}

如果你这个自定义的ModelLoader load失败了,会交给Glide默认行为继续处理的。
2. append()将确保你的ModelLoaderResourceDecoder只有在Glide默认选项都尝试后再调用,所以当你需要处理一个新的Model类型时,你需要使用append()。如当你需要通过你自定义的Model对象(Photo.class)获取InputStream时:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void registerComponents(Context context, Glide glide, Registry registry) {registry.append(Photo.class, InputStream.class, new CustomModelLoader.Factory());}
}

3.replace()将确保Glide所有给定Model和Data的ModelLoader都被替换成你的ModelLoader,所以当你不想要Glide默认行为执行,只执行你自己的加载逻辑的时候,你需要使用replace()。如当你只想使用OkHttp网络库去请求网络资源时:

@GlideModule
public class YourAppGlideModule extends AppGlideModule {@Overridepublic void registerComponents(Context context, Glide glide, Registry registry) {registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());}
}

关于配置的冲突:
你的应用可能依赖多个libraries,这些libraries可能包含多个LibraryGlideModule,有些情况下这些LibraryGlideModule的options存在冲突或者有些options是你的应用不需要或者避免的,此时你可以给你应用的AppGlideModule添加@Excludes注解去解决冲突,如:

@Excludes({com.example.unwanted.GlideModule.class, com.example.conflicing.GlideModule.class})
@GlideModule
public final class MyAppGlideModule extends AppGlideModule { }

@Excludes注解既可以用于排除LibraryGlideModule,也可用于排除你之前使用v3版本时定义的GlideModule

关于之前使用v3版本时在AndroidManifest.xml中定义的 GlideModule:
Glide v4为了向后兼容,更平滑的从v3过渡到v4,依然会解析应用和其libraries的AndroidManifest.xml文件并注册其中的GlideModule
如果你的应用和其libraries都已经是Glide v4的AppGlideModuleLibraryGlideModule,你完全可以禁用manifest解析以提高Glide初始化速度并避免潜在的解析问题:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {@Overridepublic boolean isManifestParsingEnabled() {return false;}
}

使用技巧

Glide的图片变换(Transformations)

当你使用Glide为ImageView加载图片时,Glide会根据ImageView的ScaleType自动应用相应的变换,如果scale type是CENTER_CROP,Glide将自动应用CenterCrop transformation,如果scale type是FIT_CENTERCENTER_INSIDE,Glide将自动应用FitCenter transformation。
很多情况下,我们需要对要显示的Resources (如Drawables, Bitmaps)进行裁剪、滤镜、模糊等处理,所以Glide内置了几种常用的transformations:

  • CenterCrop
  • FitCenter
  • CenterInside
  • CircleCrop
  • RoundedCorners

应用这些transformations也很简单:

RequestOptions requestOptions = new RequestOptions().fitCenter();
Glide.with(fragment).load(url).apply(requestOptions).into(imageView);
import static com.bumptech.glide.request.RequestOptions.fitCenterTransform;
Glide.with(fragment).load(url).apply(fitCenterTransform()).into(imageView);
GlideApp.with(fragment).load(url).fitCenter().into(imageView);
GlideApp.with(fragment).load(url).transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation()).into(imageView);
GlideApp.with(fragment).load(url).transforms(new FitCenter(), new YourCustomTransformation()).into(imageView);

其实本质都是调用RequestOptionstransform()方法,对于多个变换来说,MultiTransformation构造器的参数顺序决定了变换的应用顺序。
如果需要更多的图片变换可以参考 shangmingchao/GlideTransformation 或 wasabeef/glide-transformations 的自定义Transformations。

Glide的过渡动画(Transitions)

前面已经提到了,Glide的Transitions可以让图片更平滑地展示,但是在Android中使用动画是非常昂贵的,尤其是一次开启很多动画。而Cross fade及其他过渡动画对于透明度的动态改变也是特别昂贵的,更糟糕的情况下动画的执行时间甚至比解码所花费的时间还要长,所以无理由地在列表中使用动画可能会造成卡顿。为了最大化性能,最好避免在ListViewGridViewRecyclerView中使用Glide的加载动画,尤其是你希望图片更快的显示和缓存时。
Glide默认的cross fades动画是基于Android的TransitionDrawable的,TransitionDrawable提供了两种动画模式,由setCrossFadeEnabled()方法控制,当cross fades被禁用时,过渡图片会淡入到已显示的图片上面,当cross fades启用时,过渡图片会从透明逐渐变成不透明,之前的图片会从不透明变成透明。
Glide默认是禁用cross fades的,因为启用时两个图片透明度的同时变化可能会产生白色闪烁,还是禁用更好一点。但禁用cross fades也会产生一些问题:当placeholder比要加载的图片大或者要加载的图片是透明的时,禁用cross fades将会导致placeholder显示在要显示的图片下面。 你可以使用new DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true))启用cross fades。
Android TransitionDrawable 的cross fades动画还有个Bug,如果两张图片的宽高比不一样,会导致图片变形,所以慎用cross fades动画。

Glide的缓存管理(Caching)

Glide在开始一个新的图片请求之前,会检查一下各级缓存:

  1. Active resources - 要加载的图片是否正显示在其他View上?
  2. Memory cache - 要加载的图片是否最近加载过且还在内存中?
  3. Resource - 要加载的图片是否已经被解码、变换且写入过磁盘缓存?
  4. Data - 要加载的图片的原始data是否可以从磁盘缓存中获取到?

前两步是检查图片资源是否在内存中,如果在则马上返回图片资源。后两步是检查图片资源是否在磁盘缓存中,如果是则尽快异步返回图片资源。
如果这4步都没能获取到图片,Glide才会根据model(如File, Uri, Url)去获取原始资源。
Glide中缓存的cache keys包含很多元素,至少包括model(如File, Uri, Url)和可选的Signature。事实上,第1-3步(Active resources, memory cache, resource disk cache)的cache keys还是包括图片的宽高、可选的Transformation、已添加的Options以及请求的数据类型 (如Bitmap, GIF)等元素,为了生成磁盘缓存上的cache keys名称,cache keys的每个元素都会被哈希化以创建一个String key,并在随后作为磁盘缓存上的文件名使用。
可以使用RequestOptionsdiskCacheStrategy()方法为某个请求指定磁盘缓存策略,默认的缓存策略是AUTOMATIC:

  • AUTOMATIC - 请求远程数据时只缓存未经更改的原始data,请求本地数据时将缓存变换后的resource
  • DATA - 缓存未经decoded的原始data
  • RESOURCE 缓存decoded后的resource
  • ALL - 请求远程数据时缓存DATARESOURCE,请求本地数据时只缓存RESOURCE
  • NONE 不缓存
GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);

有些情况下(如无图模式/省流模式),我们希望Glide只从缓存中获取图片资源,可以借助RequestOptionsonlyRetrieveFromCache()方法:

GlideApp.with(fragment).load(url).onlyRetrieveFromCache(true).into(imageView);

跳过内存缓存:

GlideApp.with(fragment).load(url).skipMemoryCache(true).into(view);

跳过磁盘缓存:

GlideApp.with(fragment).load(url).diskCacheStrategy(DiskCacheStrategy.NONE).into(view);

清除内存缓存:

// 必须在主线程中调用
Glide.get(context).clearMemory();

清除磁盘缓存:

// 必须在工作线程中调用
Glide.get(applicationContext).clearDiskCache();

刷新缓存: 你可以通过RequestOptionssignature()方法向内存缓存和磁盘缓存的cache keys中添加额外的数据元素,以更自由地控制缓存失效与刷新。如你想要版本号也作为cache keys的一部分,当版本号更改时刷新这些缓存:

GlideApp.with(yourFragment).load(yourFileDataModel).signature(new ObjectKey(yourVersionMetadata)).into(yourImageView);

Glide v4详解相关推荐

  1. Glide使用详解(一)

    该文章基于Glide v3.7.0版本 Glide v4版本详解请移步: http://blog.csdn.net/shangmingchao/article/details/78219558 一. ...

  2. Android平滑图片加载和缓存库 Glide 使用详解

    版权声明:本文原创作者:一叶飘舟 作者博客地址:http://blog.csdn.net/jdsjlzx 一.简介 在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide的图片加载库,作者 ...

  3. Android开发中显示图片Glide使用详解(Google推荐)

    一.简介 Glide,一个被google所推荐的图片加载库,作者是bumptech.这个库被广泛运用在google的开源项目中,包括2014年的google I/O大会上发布的官方app.(PS:众所 ...

  4. Android平滑图片加载和缓存库Glide使用详解

    在图片加载库烂大街的今天,选择一个适合自己使用的图片加载库已经成为了每一个Android开发者的必经之路.现在市面上知名的图片加载库有UIL,Picasso,Volley ImageLoader,Fr ...

  5. 图片加载框架Glide使用详解

    最终我还是决定使用Glide,作为我以后的主要图片加载框架.主要基于三点考虑 代码有人维护,不至于出现问题,项目组都搞不定的时候问题无法解决.(ImageLoader已没人维护了) 代码简洁,可读性很 ...

  6. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 ALS V4地面站立动作状态机详解

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的 ...

  7. android V1,V2,V3,V4签名详解

    前言 最近帮测试做了一点关于签名的需求,今天就和各位同学简单聊一聊关于签名的那些事儿. 如果问到 Android 为什么需要签名?大家都可能想到官网的解释: ❝ Android 系统要求所有 APK ...

  8. thinksnsv4.6运行php,SNS社交系统“ThinkSNS V4.6”活动应用功能详解及应用场景举例...

    ThinkSNS是什么? ThinkSNS(简称TS)是一款起始于2008年的全平台综合性的sns社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS ...

  9. [玩转UE4/UE5动画系统>应用篇>功能模块] 之 ALS V4 主状态机详解

    本教程采用图文教程+视频教程的多元化形式,我会为不同的知识点选择适当的表达方式.教程内容将同步免费发布于 开发游戏的老王(知乎|CSDN)的专栏<玩转UE4/UE5动画系统>.教程中使用的 ...

最新文章

  1. Socket IO与NIO(二)
  2. 电子电路基础复习 —— 三极管
  3. 第三届传智杯全国大学生IT技能大赛(决赛B组)【c++】
  4. UVA - 1415 Gauss Prime(高斯素数)
  5. 谈下关于kaggle的反作弊规则
  6. 【Leetcode | 】93. 复原IP地址
  7. 对不起,我把APP也给爬了
  8. 怎么在QQ浏览器上使用微信聊天?
  9. 中文情感分析——snownlp类库 源码注释及使用
  10. 译:在C#中使用LINQ To SQL
  11. 三个步骤教你-----如何实现DHCP中继配置
  12. 激情彭拜的10月英语学习
  13. 华为数字化转型之道第四讲
  14. ​【技术】机器视觉技术原理解析及应用领域
  15. JavaWeb HTML
  16. Nand2Tetris - Week 1
  17. 2018省赛第九届蓝桥杯真题C语言B组第九题题解 全球变暖
  18. MYSQL数据库设计和数据库设计实例(二)
  19. SAML 协议-简单的SAML
  20. 从三室心脏MRI影像检测主动脉瓣病变

热门文章

  1. 超详细的 Wireshark 使用教程
  2. 在vue中禁止input框和textarea编辑的操作
  3. 三国志战略版:三势贾的另类搭配,也可以这么强?
  4. 【PyTorch】模型 FPS 测试 Benchmark(参考 MMDetection 实现)
  5. linux命令 查看分辨率,linux怎样在命令行模式修改屏幕分辨率
  6. 按键精灵9.5.1.11790秒速启动,多余元素全灭版
  7. android studio zbar,Zbar and Zxing in android studio
  8. 测试开发 | 接口测试之HTTP 协议讲解
  9. execjs安装及相关问题解决
  10. ListT的各种排序方法