#### 概述
Glide是一个Android的图片加载和缓存库,它主要专注于大量图片的流畅加载,Glide几乎可以胜任任何你需要使用到图片从网络拉取,压缩,显示的场景。
本文主要基于Glide4.0版本介绍其基本使用方法。
## 1 集成
Github地址: [https://github.com/bumptech/glide](https://github.com/bumptech/glide)
app或lib级别的`build.gradle`文件添加依赖:
~~~
dependencies {
compile 'com.github.bumptech.glide:glide:4.0.0-RC1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC1'
}
~~~
在`proguard.pro`/`proguard.cfg`中添加混淆:
~~~
-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 *;
}
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
~~~
## 2 基本用法
大多数情况下**加载图片**只需要一行代码:
~~~
Glide.with(fragment)
.load(myUrl)
.into(imageView);
~~~
**取消加载**也很简单:
~~~
Glide.with(fragment).clear(imageView);
~~~
实际上你并不需要取消加载。。。
因为当你在`with`方法中传入的`Activity`或`Fragment`被销毁的时候,Glide会自动取消加载并且回收所有的加载过程中所使用的资源。
## 3 注解(V4新特性)和自定义方法
Glide使用了`annotation processor`来生成API,允许应用修改`RequestBuilder`、`RequestOptions`和任意的包含在单一流式API库中的方法。这是V4的特性,运用注解后使用起来更方便:
~~~
GlideApp.with(fragment)
.load(myUrl)
.placeholder(R.drawable.placeholder)
.fitCenter()
.into(imageView);
~~~
Glidev4中的`Glide.with().load()`后没有之前版本的`fitCenter`和`placeholder`这样的方法,但是`GlideApp`有,可以直接在builder中使用。`GlideApp`可以代替之前版本的`Glide`开头。
这样做的目的是:
> 1.对于library项目来讲可以使用自定义方法继承Glide的API
> 2.对于应用来讲,在继承Glide的API后,可以通过添加自定义方法。
虽然你也可以手动继承`RequestOptions`,但是显然这样做更加麻烦,也破坏了流式API特性。
### 3.1 在项目中实现`AppGlideModule`:
~~~
@GlideModule
public class CustomGlideModule extends AppGlideModule {}
~~~
这个类实现必须要有`@GlideModule`注解,如果你添加的方法失效,那就检查下这里。
如果是library就实现`LibraryGlideModule`,以使用OkHttp为例:
~~~
@GlideModule
public final class OkHttpLibraryGlideModule extends LibraryGlideModule {
@Override
public void registerComponents(Context context, Registry registry) {
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
}
}
~~~
[OkHttpUrlLoader](https://github.com/bumptech/glide/blob/master/integration/okhttp3/src/main/java/com/bumptech/glide/integration/okhttp3/OkHttpUrlLoader.java)是Glide的OKHttp扩展库中的类,如果需要使用Glide的实现,可以在依赖中添加:
~~~
compile 'com.github.bumptech.glide:okhttp3-integration:4.0.0-RC1'
~~~
添加完依赖不需要自己实现OkHttpLibraryGlideModule类,库中已经自带了,会自动使用OKHttp的。
然后编译工程可以发现在build中生成了四个类:
![](http://img.blog.csdn.net/20170706120245250?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzAwNTc5MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
### 3.2 GlideExtension
为了添加新的方法,修改已有的方法或者添加对其他类型格式的支持,你需要在扩展中使用加了注解的静态方法。
`GlideOption`用来添加自定义的方法,`GlideType`用来支持新的格式。
#### 3.2.1 GlideOption
先新建一个`CustomGlideExtension`类:
~~~
@GlideExtension
public class CustomGlideExtension {
//缩略图的最小尺寸,单位:px
private static final int MINI_THUMB_SIZE = 100;
/**
* 将构造方法设为私有,作为工具类使用
*/
private CustomGlideExtension() {
}
/**
* 1.自己新增的方法的第一个参数必须是RequestOptions options
* 2.方法必须是静态的
* @param options
*/
@GlideOption
public static void miniThumb(RequestOptions options) {
options
.fitCenter()
.override(MINI_THUMB_SIZE);
}
}
~~~
编译工程,打开build目录中的`GlideOptions`,可以看见自动生成了两个方法:
~~~
public class GlideOptions extends RequestOptions {
/**
* @see CustomGlideExtension#miniThumb(RequestOptions)
*/
public GlideOptions miniThumb() {
CustomGlideExtension.miniThumb(this);
return this;
}
/**
* @see CustomGlideExtension#miniThumb(RequestOptions)
*/
public static GlideOptions miniThumbOf() {
return new GlideOptions().miniThumb();
}
...
}
~~~
现在可以使用你自定义的方法了:
~~~
GlideApp.with(fragment)
.load(url)
.miniThumb(thumbnailSize)
.into(imageView);
~~~
#### 3.2.2 GlideType
以添加对`GIF`格式的支持为例,只是举例,实际上API中已经支持了。
在刚才的`CustomGlideExtension`类中加上:
~~~
@GlideExtension
public class CustomGlideExtension {
private static final RequestOptions DECODE_TYPE_GIF = GlideOptions.decodeTypeOf(GifDrawable.class).lock();
@GlideType(GifDrawable.class)
public static void asGIF(RequestBuilder<GifDrawable> requestBuilder) {
requestBuilder
.transition(new DrawableTransitionOptions())
.apply(DECODE_TYPE_GIF);
}
}
~~~
编译工程,打开build目录中的`GlideRequests`,可以看见自动生成了一个方法:
~~~
public class GlideRequests extends RequestManager {
/**
* @see CustomGlideExtension#asGIF(RequestBuilder)
*/
public GlideRequest<GifDrawable> asGIF() {
GlideRequest<GifDrawable> requestBuilder = this.as(GifDrawable.class);
CustomGlideExtension.asGIF(requestBuilder);
return requestBuilder;
}
}
~~~
现在可以使用你添加的类型了:
~~~
GlideApp.with(fragment)
.asGIF()
.load(url)
.into(imageView);
~~~
## 4 占位符
占位符就是请求的图片没加载出来时显示的默认图片。
Glide支持三种不同情况下的占位符:
* Placeholder 请求图片加载中
* Error 请求图片加载错误
* Fallback 请求url/model为空
### 设置占位符:
~~~
GlideApp.with(fragment)
.load(url)
.placeholder(R.drawable.placeholder)
.error(new ColorDrawable(Color.RED))
.fallback(new ColorDrawable(Color.GREY))
.into(view);
~~~
之后的显示优先级,我画了个流程图。
![](http://img.blog.csdn.net/20170706120204646?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzAwNTc5MQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
## 5 Options
### 5.1 RequestOptions
Glide中的大多请求参数都可以通过`RequestOptions`类和`apply()`方法来设置。
Glide中的请求参数主要有:
* Placeholders 占位符
* Transformations 变换
* Caching Strategies 缓存策略
* 组件特定参数:编码质量,解码参数等。
比如,要将图片的显示方式设为`CenterCrop`,你可以这么做:
~~~
import static com.bumptech.glide.request.RequestOptions.centerCropTransform;
Glide.with(fragment)
.load(url)
.apply(centerCropTransform(context))
.into(imageView);
~~~
但是其实完全可以在layout文件中设置ImageView为`android:scaleType="centerCrop"`,Glide会自动根据这个属性设置图片的显示方式。
`apply`方法可以调用多次,但是如果两次`apply`存在冲突的设置,会以最后一次为准。
### 5.2 TransitionOptions
[`TransitionOptions`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/TransitionOptions.html)决定图片加载完成如何从占位符图片(或者之前的图片)过渡。
* 淡入
* 交叉淡入
* 不过渡
~~~
Glide.with(fragment)
.load(url)
.transition(DrawableTransitionOptions.withCrossFade())
.into(view);
~~~
**注意**
> [`TransitionOptions`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/TransitionOptions.html)是和你要加载的资源的类型绑定的,也就是说,如果你请求一张位图(Bitmap),你就需要使用[`BitmapTransitionOptions`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/resource/bitmap/BitmapTransitionOptions.html),而不是[`DrawableTransitionOptions`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/resource/drawable/DrawableTransitionOptions.html)。因此,你请求的这张位图,你需要用简单的淡入,而不能用
> 交叉淡入([`DrawableTransitionOptions.withCrossFade()`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/resource/drawable/DrawableTransitionOptions.html#withCrossFade--))。
> 如果既不是Bitmap也不是Drawable可以使用[GenericTransitionOptions](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/GenericTransitionOptions.html)
### 5.3 RequestBuilder
**作用:**
> 1. 指定加载类型。`asBitmap()`、`asGif()`、`asDrawable()`、`asFile()`。
> 2. 指定要加载url/model。
> 3. 指定要加载到那个View。
> 4. 指定要应用的`RequestOption`
> 5. 指定要应用的`TransitionOption`
> 6. 指定要加载的缩略图
那么如何得到`RequestBuilder`呢?
~~~
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment);
~~~
默认得到一个`Drawable RequestBuilder`,如果要指定类型为Bitmap,可以这样写:
~~~
RequestBuilder<Bitmap> requestBuilder = Glide.with(fragment).asBitmap();
~~~
**应用`RequestOptions`**
~~~
RequestBuilder<Drawable> requestBuilder = Glide.with(fragment);
requestBuilder.apply(requestOptions);
requestBuilder.transition(transitionOptions);
~~~
`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);
}
~~~
## 6 Transformations
Glide会自动读取ImageView的缩放类型,所以一般在layout文件指定`scaleType`即可。
CenterCrop, CenterInside, CircleCrop, FitCenter, RoundedCorners
Glide支持在java代码中设置这些缩放类型:
> 1. CenterCrop 缩放宽和高都到达View的边界,有一个参数在边界上,另一个参数可能在边界上,也可能超过边界
> 2. CenterInside 如果宽和高都在View的边界内,那就不缩放,否则缩放宽和高都进入View的边界,有一个参数在边界上,另一个参数可能在边界上,也可能在边界内
> 3. CircleCrop 圆形且结合了CenterCrop的特性
> 4. FitCenter 缩放宽和高都进入View的边界,有一个参数在边界上,另一个参数可能在边界上,也可能在边界内
> 5. RoundedCorners 圆角
有三种用法:
### 1 使用RequestOptions
~~~
RequestOptions options = new RequestOptions();
options.centerCrop();
Glide.with(fragment)
.load(url)
.apply(options)
.into(imageView);
~~~
### 2 使用RequestOptions中的transform方法
~~~
Glide.with(fragment)
.load(url)
.apply(RequestOptions.fitCenterTransform())
.into(imageView);
~~~
### 3 V4特性
~~~
GlideApp.with(fragment)
.load(url)
.fitCenter()
.into(imageView);
~~~
第三种方法最简便,推荐。
### 多个变换
~~~
Glide.with(fragment)
.load(url)
.transform(new MultiTransformation(new FitCenter(), new YourCustomTransformation())
.into(imageView);
~~~
## 7 Transitions(动画)
### 普通动画
Glide中的过渡动画是指占位符到请求图片或缩略图到完整尺寸请求图片的动画。过渡动画只能针对单一请求,不能跨请求执行。
过渡动画执行时机:
> 1.图片在磁盘缓存
> 2.图片在本地
> 3.图片在远程
如果图片在内存缓存上是不会执行过渡动画的。如果需要在内存缓存上加载动画,可以这样:
~~~
GlideApp.with(this).load(R.drawable.img_default).listener(new RequestListener(){
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Object resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
if (dataSource == DataSource.MEMORY_CACHE) {
//当图片位于内存缓存时,glide默认不会加载动画
imageView.startAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.fade_in));
}
return false;
}
}).fitCenter().transition(GenericTransitionOptions.with(R.anim.fade_in)).into(imageView);
~~~
通常的用法如下:
~~~
Glide.with(fragment)
.load(url)
.transition(DrawableTransitionOptions.withCrossFade())
.into(view);
~~~
`TransitionOptions`的介绍:[TransitionOptions](http://blog.csdn.net/u013005791/article/details/74532091#TransitionOptions)。有三种TransitionOptions:
1. `GenericTransitionOptions` 通用型
2. `DrawableTransitionOptions`
3. `BitmapTransitionOptions`
如果要使用自定义的动画,可以使用`GenericTransitionOptions.with(int viewAnimationId)`或者`BitmapTransitionOptions.withCrossFade(int animationId, int duration)`或者`DrawableTransitionOptions.withCrossFade(int animationId, int duration)`。
出于性能考虑,最好不要在ListView,GridView,RecycleView中使用过渡动画,使用`TransitionOptions.dontTransition()`可以不加载动画,也可以使用`dontAnimate`不加载动画
~~~
GlideApp.with(mContext)
.load(imgUrl)
.placeholder(R.drawable.img_default)
.dontAnimate()
.into(holder.imageview);
~~~
### 自定义过渡动画
**1.实现[`TransitionFactory`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/request/transition/TransitionFactory.html)**
**2.重写[`build()`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/request/transition/TransitionFactory.html#build-com.bumptech.glide.load.DataSource-boolean-)**
可以控制图片在内存缓存上是否执行动画。
具体写法参考[DrawableCrossFadeFactory](https://github.com/bumptech/glide/blob/8f22bd9b82349bf748e335b4a31e70c9383fb15a/library/src/main/java/com/bumptech/glide/request/transition/DrawableCrossFadeFactory.java#L35),然后调用`TransitionOptions`的`with(TransitionFactory transitionFactory)`加载。
## 8 基本配置
### 8.1 配置内存缓存
Glide会自动合理分配内存缓存,但是也可以自己手动分配。
#### 方法一
通过MemorySizeCalculator设置
~~~
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
.setMemoryCacheScreens(2)
.build();
builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
}
}
~~~
[`setMemoryCacheScreens`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/engine/cache/MemorySizeCalculator.Builder.html#setMemoryCacheScreens-float-)设置MemoryCache应该能够容纳的像素值的设备屏幕数,说白了就是缓存多少屏图片,默认值是2。
#### 方法二
~~~
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb
builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));
}
}
~~~
#### 方法三
~~~
@GlideModule
public class YourAppGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setMemoryCache(new CustomGlideMemoryCache());
}
}
~~~
自己实现[`MemoryCache`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/engine/cache/MemoryCache.html)接口。
清楚内存缓存,在主线程调用:
~~~
GlideApp.get(context).clearMemory();
~~~
在使用的时候,可以跳过内存缓存:
~~~
GlideApp.with(getActivity())
.load(url)
.skipMemoryCache(true)
.dontAnimate()
.centerCrop()
.into(imageView);
~~~
### 8.2 磁盘缓存
Glide使用[`DiskLruCacheWrapper`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/engine/cache/DiskLruCacheWrapper.html)作为默认的磁盘缓存,默认大小是250M,缓存文件放在APP的缓存文件夹下。
~~~
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
int diskCacheSizeBytes = 1024 * 1024 * 100; // 100 MB
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));
// builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "cacheFolderName", diskCacheSizeBytes));
// builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));
}
}
~~~
用法如上,可以指定缓存在内部存储或外部存储,也可以指定缓存大小和文件夹。
**自定义磁盘缓存**
~~~
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDiskCache(new DiskCache.Factory() {
@Override
public DiskCache build() {
return new YourAppCustomDiskCache();
}
});
}
}
~~~
自己实现[`DiskCache`](http://bumptech.github.io/glide/javadocs/400/com/bumptech/glide/load/engine/cache/DiskCache.html)接口。
清楚磁盘缓存,在主线程调用:
~~~
GlideApp.get(context).clearDiskCache();
~~~
加载图片时设置磁盘缓存策略:
~~~
GlideApp.with(getActivity())
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.dontAnimate()
.centerCrop()
.into(imageView);
~~~
默认的策略是`DiskCacheStrategy.AUTOMATIC`
DiskCacheStrategy有五个常量:
* DiskCacheStrategy.ALL 使用DATA和RESOURCE缓存远程数据,仅使用RESOURCE来缓存本地数据。
* DiskCacheStrategy.NONE 不使用磁盘缓存
* DiskCacheStrategy.DATA 在资源解码前就将原始数据写入磁盘缓存
* DiskCacheStrategy.RESOURCE 在资源解码后将数据写入磁盘缓存,即经过缩放等转换后的图片资源。
* DiskCacheStrategy.AUTOMATIC 根据原始图片数据和资源编码策略来自动选择磁盘缓存策略。
### 8.3 禁止解析Manifest文件
主要针对V3升级到v4的用户,可以提升初始化速度,避免一些潜在错误。
~~~
@GlideModule
public class CustomGlideModule extends AppGlideModule {
@Override
public boolean isManifestParsingEnabled() {
return false;
}
}
~~~
### 8.4 View尺寸
Glide对ImageView的`width`和`height`属性是这样解析的:
> * 如果`width`和`height`都大于0,则使用layout中的尺寸。
> * 如果`width`和`height`都是`WRAP_CONTENT`,则使用屏幕尺寸。
> * 如果`width`和`height`中至少有一个值<=0并且不是`WRAP_CONTENT`,那么就会在布局的时候添加一个`OnPreDrawListener`监听ImageView的尺寸
Glide对`WRAP_CONTENT`的支持并不好,所以尽量不要用。
那么如何在运行修改ImageView尺寸呢?
#### 方法一 继承ImageViewTarget
我这里指定的View的类型是ImageView,资源类型是Bitmap,可根据需要修改,`onResourceReady(Bitmap bitmap, Transition<? super Bitmap> transition)`方法中可以通过bitmap获取图片的尺寸。
~~~
public class CustomImageViewTarget extends ImageViewTarget<Bitmap> {
private int width, height;
public CustomImageViewTarget(ImageView view) {
super(view);
}
public CustomImageViewTarget(ImageView view, int width, int height) {
super(view);
this.width = width;
this.height = height;
}
@Override
public void onResourceReady(Bitmap bitmap, Transition<? super Bitmap> transition) {
}
@Override
protected void setResource(@Nullable Bitmap resource) {
view.setImageBitmap(resource);
}
@Override
public void getSize(SizeReadyCallback cb) {
if (width > 0 && height > 0) {
cb.onSizeReady(width, height);
return;
}
super.getSize(cb);
}
}
~~~
使用:
~~~
GlideApp.with(context)
.asBitmap()
.load(url)
.dontAnimate()
.placeholder(R.drawable.img_default)
.into(new CustomImageViewTarget(imageview, 300, 300));
~~~
#### 方法二 使用override()
~~~
GlideApp.with(mContext)
.load(url)
.override(width,height)
.into(view);
~~~
### 8.5 Recycle的加载优化
只在拖动和静止时加载,自动滑动时不加载。
~~~
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_DRAGGING:
GlideApp.with(context).resumeRequests();
break;
case RecyclerView.SCROLL_STATE_SETTLING:
GlideApp.with(context).pauseRequests();
break;
case RecyclerView.SCROLL_STATE_IDLE:
GlideApp.with(context).resumeRequests();
break;
}
}
});
~~~
- 0-发现
- AndroidInterview-Q-A
- Android能让你少走弯路的干货整理
- LearningNotes
- temp
- temp11
- 部分地址
- 0-待办任务
- 待补充列表
- 0-未分类
- AndroidView事件分发与滑动冲突处理
- Spannable
- 事件分发机制详解
- 1-Java
- 1-Java-01基础
- 未归档
- 你应该知道的JDK知识
- 集合框架
- 1-Java-04合集
- Java之旅0
- Java之旅
- JAVA之旅01
- JAVA之旅02
- JAVA之旅03
- JAVA之旅04
- JAVA之旅05
- JAVA之旅06
- JAVA之旅07
- JAVA之旅08
- JAVA之旅09
- java之旅1
- JAVA之旅10
- JAVA之旅11
- JAVA之旅12
- JAVA之旅13
- JAVA之旅14
- JAVA之旅15
- JAVA之旅16
- JAVA之旅17
- JAVA之旅18
- JAVA之旅19
- java之旅2
- JAVA之旅20
- JAVA之旅21
- JAVA之旅22
- JAVA之旅23
- JAVA之旅24
- JAVA之旅25
- JAVA之旅26
- JAVA之旅27
- JAVA之旅28
- JAVA之旅29
- java之旅3
- JAVA之旅30
- JAVA之旅31
- JAVA之旅32
- JAVA之旅33
- JAVA之旅34
- JAVA之旅35
- 1-Java-05辨析
- HashMapArrayMap
- Java8新特性
- Java8接口默认方法
- 图解HashMap(1)
- 图解HashMap(2)
- 2-Android
- 2-Android-1-基础
- View绘制流程
- 事件分发
- AndroidView的事件分发机制和滑动冲突解决
- 自定义View基础
- 1-安卓自定义View基础-坐标系
- 2-安卓自定义View基础-角度弧度
- 3-安卓自定义View基础-颜色
- 自定义View进阶
- 1-安卓自定义View进阶-分类和流程
- 10-安卓自定义View进阶-Matrix详解
- 11-安卓自定义View进阶-MatrixCamera
- 12-安卓自定义View进阶-事件分发机制原理
- 13-安卓自定义View进阶-事件分发机制详解
- 14-安卓自定义View进阶-MotionEvent详解
- 15-安卓自定义View进阶-特殊形状控件事件处理方案
- 16-安卓自定义View进阶-多点触控详解
- 17-安卓自定义View进阶-手势检测GestureDetector
- 2-安卓自定义View进阶-绘制基本图形
- 3-安卓自定义View进阶-画布操作
- 4-安卓自定义View进阶-图片文字
- 5-安卓自定义View进阶-Path基本操作
- 6-安卓自定义View进阶-贝塞尔曲线
- 7-安卓自定义View进阶-Path完结篇伪
- 8-安卓自定义View进阶-Path玩出花样PathMeasure
- 9-安卓自定义View进阶-Matrix原理
- 通用类介绍
- Application
- 2-Android-2-使用
- 2-Android-02控件
- ViewGroup
- ConstraintLayout
- CoordinatorLayout
- 2-Android-03三方使用
- Dagger2
- Dagger2图文完全教程
- Dagger2最清晰的使用教程
- Dagger2让你爱不释手-终结篇
- Dagger2让你爱不释手-重点概念讲解、融合篇
- dagger2让你爱不释手:基础依赖注入框架篇
- 阅读笔记
- Glide
- Google推荐的图片加载库Glide:最新版使用指南(含新特性)
- rxjava
- 这可能是最好的RxJava2.x入门教程完结版
- 这可能是最好的RxJava2.x入门教程(一)
- 这可能是最好的RxJava2.x入门教程(三)
- 这可能是最好的RxJava2.x入门教程(二)
- 这可能是最好的RxJava2.x入门教程(五)
- 这可能是最好的RxJava2.x入门教程(四)
- 2-Android-3-优化
- 优化概况
- 各种优化
- Android端秒开优化
- apk大小优化
- 内存分析
- 混淆
- 2-Android-4-工具
- adb命令
- 一键分析Android的BugReport
- 版本控制
- git
- git章节简述
- 2-Android-5-源码
- HandlerThread 源码分析
- IntentService的使用和源码分析
- 2-Android-9-辨析
- LRU算法
- 什么是Bitmap
- 常见图片压缩方式
- 3-Kotlin
- Kotlin使用笔记1-草稿
- Kotlin使用笔记2
- kotlin特性草稿
- Kotlin草稿-Delegation
- Kotlin草稿-Field
- Kotlin草稿-object
- 4-JavaScript
- 5-Python
- 6-Other
- Git
- Gradle
- Android中ProGuard配置和总结
- gradle使用笔记
- Nexus私服搭建
- 编译提速最佳实践
- 7-设计模式与架构
- 组件化
- 组件化探索(OKR)
- 1-参考列表
- 2-1-组件化概述
- 2-2-gradle配置
- 2-3-代码编写
- 2-4-常见问题
- 2-9-值得一读
- 8-数据结构与算法
- 0临时文件
- 汉诺塔
- 8-数据-1数据结构
- HashMap
- HashMap、Hashtable、HashSet 和 ConcurrentHashMap 的比较
- 迟到一年HashMap解读
- 8-数据-2算法
- 1个就够了
- Java常用排序算法(必须掌握的8大排序算法)
- 常用排序算法总结(性能+代码)
- 必须知道的八大种排序算法(java实现)
- 9-职业
- 阅读
- 书单
- 面试
- 面试-01-java
- Java面试题全集骆昊(上)
- Java面试题全集骆昊(下)
- Java面试题全集骆昊(中)
- 面试-02-android
- 40道Android面试题
- 面试-03-开源源码
- Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程
- 面试-07-设计模式
- 面试-08-算法
- 面试-09-其他
- SUMMARY
- 版权说明
- temp111