Glide 系列-1:預(yù)熱优构、Glide 的常用配置方式及其原理

在接下來的幾篇文章中,我們會(huì)對 Android 中常用的圖片加載框架 Glide 進(jìn)行分析雁竞。在本篇文章中钦椭,我們先通過介紹 Glide 的幾種常用的配置方式來了解 Glide 的部分源碼拧额。后續(xù)的文中,我們會(huì)對 Glide 的源碼進(jìn)行更詳盡的分析彪腔。

對于 Glide侥锦,相信多數(shù) Android 開發(fā)者并不陌生,在本文中德挣,我們不打算對其具體使用做介紹恭垦,你可以通過查看官方文檔進(jìn)行學(xué)習(xí)。Glide 的 API 設(shè)計(jì)非常人性化格嗅,上手也很容易番挺。

在這篇文中中我們主要介紹兩種常用的 Glide 的配置方式,并以此為基礎(chǔ)來分析 Glide 的工作原理吗浩。在本文中我們將會(huì)介紹的內(nèi)容有:

  1. 通過自定義 GlideModule 指定 Glide 的緩存路徑和緩存空間的大薪ㄜ健;
  2. 帶有時(shí)間戳的圖片的緩存命中問題的解決懂扼;
  3. 在 Glide 中使用 OkHttp 作為網(wǎng)絡(luò)中的圖片資源加載方式的實(shí)現(xiàn)禁荸。

1、自定義圖片加載方式

有時(shí)候阀湿,我們需要對 Glide 進(jìn)行配置來使其能夠?qū)μ厥忸愋偷膱D片進(jìn)行加載和緩存赶熟。考慮這么一個(gè)場景:圖片路徑中帶有時(shí)間戳陷嘴。這種情形比較場景映砖,即有時(shí)候我們通過為圖片設(shè)置時(shí)間戳來讓圖片鏈接在指定的時(shí)間過后失效,從而達(dá)到數(shù)據(jù)保護(hù)的目的灾挨。

在這種情況下邑退,我們需要解決幾個(gè)問題:1).需要配置緩存的 key,不然緩存無法命中劳澄,每次都需要從網(wǎng)絡(luò)中進(jìn)行獲鹊丶肌;2).根據(jù)正確的鏈接秒拔,從網(wǎng)絡(luò)中獲取圖片并展示莫矗。

我們可以使用自定義配置 Glide 的方式來解決這個(gè)問題。

1.1 帶時(shí)間戳圖片加載的實(shí)現(xiàn)

1.1.1 MyAppGlideModule

首先砂缩,按照下面的方式自定義 GlideModule作谚,

    @GlideModule
    public class MyAppGlideModule extends AppGlideModule {

        /**
        * 配置圖片緩存的路徑和緩存空間的大小
        */
        @Override
        public void applyOptions(Context context, GlideBuilder builder) {
            builder.setDiskCache(new InternalCacheDiskCacheFactory(context, Constants.DISK_CACHE_DIR, 100 << 20));
        }

        /**
        * 注冊指定類型的源數(shù)據(jù),并指定它的圖片加載所使用的 ModelLoader
        */
        @Override
        public void registerComponents(Context context, Glide glide, Registry registry) {
            glide.getRegistry().append(CachedImage.class, InputStream.class, new ImageLoader.Factory());
        }

        /**
        * 是否啟用基于 Manifest 的 GlideModule庵芭,如果沒有在 Manifest 中聲明 GlideModule妹懒,可以通過返回 false 禁用
        */
        @Override
        public boolean isManifestParsingEnabled() {
            return false;
        }
    }

在上面的代碼中,我們通過覆寫 registerComponents() 方法双吆,并調(diào)用 Glide 的 Registryappend() 方法來向 Glide 增加我們的自定義圖片類型的加載方式眨唬。(如果替換某種資源加載方式則需要使用 replace() 方法滔悉,此外 Registry 還有其他的方法,可以通過查看源碼進(jìn)行了解单绑。)

在上面的方法中,我們新定義了兩個(gè)類曹宴,分別是 CachedImageImageLoader搂橙。CachedImage 就是我們的自定義資源類型,ImageLoader 是該資源類型的加載方式笛坦。當(dāng)進(jìn)行圖片加載的時(shí)候区转,會(huì)根據(jù)資源的類型找到該圖片加載方式,然后使用它來進(jìn)行圖片加載版扩。

1.1.2 CachedImage

我們通過該類的構(gòu)造方法將原始的圖片的鏈接傳入废离,并通過該類的 getImageId() 方法來返回圖片緩存的鍵,在該方法中我們從圖片鏈接中過濾掉時(shí)間戳:

    public class CachedImage {

        private final String imageUrl;

        public CachedImage(String imageUrl) {
            this.imageUrl = imageUrl;
        }

        /**
        * 原始的圖片的 url礁芦,用來從網(wǎng)絡(luò)中加載圖片
        */
        public String getImageUrl() {
            return imageUrl;
        }

        /**
        * 提取時(shí)間戳之前的部分作為圖片的 key蜻韭,這個(gè) key 將會(huì)被用作緩存的 key,并用來從緩存中找緩存數(shù)據(jù)
        */
        public String getImageId() {
            if (imageUrl.contains("?")) {
                return imageUrl.substring(0, imageUrl.lastIndexOf("?"));
            } else {
                return imageUrl;
            }
        }
    }

1.1.3 ImageLoader

CachedImage 的加載通過 ImageLoader 實(shí)現(xiàn)柿扣。正如上面所說的肖方,我們將 CachedImagegetImageId() 方法得到的字符串作為緩存的鍵,然后使用默認(rèn)的 HttpUrlFetcher 作為圖片的加載方式未状。

    public class ImageLoader implements ModelLoader<CachedImage, InputStream> {

        /**
        * 在這個(gè)方法中俯画,我們使用 ObjectKey 來設(shè)置圖片的緩存的鍵
        */
        @Override
        public LoadData<InputStream> buildLoadData(CachedImage cachedImage, int width, int height, Options options) {
            return new LoadData<>(new ObjectKey(cachedImage.getImageId()),
                    new HttpUrlFetcher(new GlideUrl(cachedImage.getImageUrl()), 15000));
        }

        @Override
        public boolean handles(CachedImage cachedImage) {
            return true;
        }

        public static class Factory implements ModelLoaderFactory<CachedImage, InputStream> {

            @Override
            public ModelLoader<CachedImage, InputStream> build(MultiModelLoaderFactory multiFactory) {
                return new ImageLoader();
            }

            @Override
            public void teardown() { /* no op */ }
        }
    }

1.1.4 使用

當(dāng)我們按照上面的方式配置完畢之后就可以在項(xiàng)目中使用 CachedImage 來加載圖片了:

    GlideApp.with(getContext())
        .load(new CachedImage(user.getAvatarUrl()))
        .into(getBinding().ivAccount);

這里,當(dāng)有加載圖片需求的時(shí)候司草,都會(huì)把原始的圖片鏈接使用 CachedImage 包裝一層之后再進(jìn)行加載艰垂,其他的步驟與 Glide 的基本使用方式一致。

1.2 原理分析

當(dāng)我們啟用了 @GlideModule 注解之后會(huì)在編譯期間生成 GeneratedAppGlideModuleImpl埋虹。從下面的代碼中可以看出猜憎,它實(shí)際上就是對我們自定義的 MyAppGlideModule 做了一層包裝。這么去做的目的就是它可以通過反射來尋找 GeneratedAppGlideModuleImpl吨岭,并通過調(diào)用 GeneratedAppGlideModuleImpl 的方法來間接調(diào)用我們的 MyAppGlideModule拉宗。本質(zhì)上是一種代理模式的應(yīng)用:

    final class GeneratedAppGlideModuleImpl extends GeneratedAppGlideModule {
        private final MyAppGlideModule appGlideModule;

        GeneratedAppGlideModuleImpl() {
            appGlideModule = new MyAppGlideModule();
        }

        @Override
        public void applyOptions(Context context, GlideBuilder builder) {
            appGlideModule.applyOptions(context, builder);
        }

        @Override
        public void registerComponents(Context context, Glide glide, Registry registry) {
            appGlideModule.registerComponents(context, glide, registry);
        }

        @Override
        public boolean isManifestParsingEnabled() {
            return appGlideModule.isManifestParsingEnabled();
        }

        @Override
        public Set<Class<?>> getExcludedModuleClasses() {
            return Collections.emptySet();
        }

        @Override
        GeneratedRequestManagerFactory getRequestManagerFactory() {
            return new GeneratedRequestManagerFactory();
        }
    }

下面就是 GeneratedAppGlideModuleImpl 被用到的地方:

當(dāng)我們實(shí)例化單例的 Glide 的時(shí)候,會(huì)調(diào)用下面的方法來通過反射獲取該實(shí)現(xiàn)類(所以對生成類的混淆就是必不可少的):

    Class<GeneratedAppGlideModule> clazz = (Class<GeneratedAppGlideModule>)
            Class.forName("com.bumptech.glide.GeneratedAppGlideModuleImpl");

當(dāng)?shù)玫搅酥髸?huì)調(diào)用 GeneratedAppGlideModule 的各個(gè)方法辣辫。這樣我們的自定義 GlideModule 的方法就被觸發(fā)了旦事。(下面的方法比較重要,我們自定義 Glide 的時(shí)候許多的配置都能夠從下面的源碼中尋找到答案急灭,后文中我們?nèi)匀粫?huì)提到這個(gè)方法)

  private static void initializeGlide(Context context, GlideBuilder builder) {
    Context applicationContext = context.getApplicationContext();
    // 利用反射獲取 GeneratedAppGlideModuleImpl
    GeneratedAppGlideModule annotationGeneratedModule = getAnnotationGeneratedGlideModules();
    // 從 Manifest 中獲取 GlideModule
    List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
    if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
      manifestModules = new ManifestParser(applicationContext).parse();
    }

    // 獲取被排除掉的 GlideModule
    if (annotationGeneratedModule != null
        && !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
      Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
      Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
      while (iterator.hasNext()) {
        com.bumptech.glide.module.GlideModule current = iterator.next();
        if (!excludedModuleClasses.contains(current.getClass())) {
          continue;
        }
        iterator.remove();
      }
    }

    // 應(yīng)用 GlideModule姐浮,我們自定義 GlideModuel 的方法會(huì)在這里被調(diào)用
    RequestManagerRetriever.RequestManagerFactory factory = annotationGeneratedModule != null
        ? annotationGeneratedModule.getRequestManagerFactory() : null;
    builder.setRequestManagerFactory(factory);
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.applyOptions(applicationContext, builder);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.applyOptions(applicationContext, builder);
    }
    // 構(gòu)建 Glide 對象
    Glide glide = builder.build(applicationContext);
    for (com.bumptech.glide.module.GlideModule module : manifestModules) {
      module.registerComponents(applicationContext, glide, glide.registry);
    }
    if (annotationGeneratedModule != null) {
      annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
    }
    applicationContext.registerComponentCallbacks(glide);
    Glide.glide = glide;
  }

再回到之前的自定義 GlideModule 部分代碼中:

public void applyOptions(Context context, GlideBuilder builder) {
    builder.setDiskCache(new InternalCacheDiskCacheFactory(context, Constants.DISK_CACHE_DIR, 100 << 20));
}

這里的 applyOptions() 方法允許我們對 Glide 進(jìn)行自定義。從 initializeGlide() 方法中葬馋,我們也看出卖鲤,這里的 GlideBuilder 也就是 initializeGlide() 方法中傳入的 GlideBuilder肾扰。這里使用了構(gòu)建者模式,GlideBuilder 是構(gòu)建者的實(shí)例蛋逾。所以集晚,我們可以通過調(diào)用 GlideBuilder 的方法來對 Glide 進(jìn)行自定義。

在上面的自定義 GlideModule 中区匣,我們通過構(gòu)建者來指定了 Glide 的緩存大小和緩存路徑偷拔。 GlideBuilder 還提供了一些其他的方法,我們可以通過查看源碼了解亏钩,并調(diào)用這些方法來自定義 Glide.

2莲绰、在 Glide 中使用 OkHttp

Glide 默認(rèn)使用 HttpURLConnection 實(shí)現(xiàn)網(wǎng)絡(luò)當(dāng)中的圖片的加載。我們可以通過對 Glide 進(jìn)行配置來使用 OkHttp 進(jìn)行網(wǎng)絡(luò)圖片加載姑丑。

首先蛤签,我們需要引用如下依賴:

    api ('com.github.bumptech.glide:okhttp3-integration:4.8.0') {
        transitive = false
    }

該類庫中提供了基于 OkHttp 的 ModelLoaderDataFetcher 實(shí)現(xiàn)。它們是 Glide 圖片加載環(huán)節(jié)中的重要組成部分栅哀,我們會(huì)在后面介紹源碼和 Glide 的架構(gòu)的時(shí)候介紹它們被設(shè)計(jì)的意圖及其作用震肮。

然后,我們需要在自定義的 GlideModule 中注冊網(wǎng)絡(luò)圖片加載需要的組件留拾,即在 registerComponents() 方法中替換 GlideUrl 的加載的默認(rèn)實(shí)現(xiàn):

    @GlideModule
    @Excludes(value = {com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule.class})
    public class MyAppGlideModule extends AppGlideModule {

        private static final String DISK_CACHE_DIR = "Glide_cache";

        private static final long DISK_CACHE_SIZE = 100 << 20; // 100M

        @Override
        public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
            builder.setDiskCache(new InternalCacheDiskCacheFactory(context, DISK_CACHE_DIR, DISK_CACHE_SIZE));
        }

        @Override
        public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(15, TimeUnit.SECONDS)
                    .eventListener(new EventListener() {
                        @Override
                        public void callStart(Call call) {
                            // 輸出日志钙蒙,用于確認(rèn)使用了我們配置的 OkHttp 進(jìn)行網(wǎng)絡(luò)請求
                            LogUtils.d(call.request().url().toString());
                        }
                    })
                    .build();
            registry.replace(GlideUrl.class, InputStream.class, new Factory(okHttpClient));
        }

        @Override
        public boolean isManifestParsingEnabled() {
            // 不使用 Manifest 中的 GlideModule
            return false;
        }
    }

這樣我們通過自己的配置指定網(wǎng)絡(luò)中圖片加載需要使用 OkHttp. 并且自定義了 OkHttp 的超時(shí)時(shí)間等參數(shù)。按照上面的方式我們可以在 Glide 中使用 OkHttp 來加載網(wǎng)絡(luò)中的圖片了间驮。

不過躬厌,當(dāng)我們在項(xiàng)目中引用了 okhttp3-integration 的依賴之后惑淳,不進(jìn)行上述配置一樣可以使用 OkHttp 來進(jìn)行網(wǎng)絡(luò)圖片加載的犁跪。這是因?yàn)樯鲜鲆蕾嚨陌幸呀?jīng)提供了一個(gè)自定義的 GlideModule,即 OkHttpLibraryGlideModule涛菠。該類使用了 @GlideModule 注解屹篓,并且已經(jīng)指定了網(wǎng)絡(luò)圖片加載使用 OkHttp疙渣。所以,當(dāng)我們不自定義 GlideModule 的時(shí)候堆巧,只使用它一樣可以在 Glide 中使用 OkHttp.

如果我們使用了自定義的 GlideModule妄荔,當(dāng)我們編譯的時(shí)候會(huì)看到 GeneratedAppGlideModuleImpl 中的 registerComponents() 方法定義如下:

  @Override
  public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    new OkHttpLibraryGlideModule().registerComponents(context, glide, registry);
    appGlideModule.registerComponents(context, glide, registry);
  }

這里先調(diào)用了 OkHttpLibraryGlideModuleregisterComponents() 方法,然后調(diào)用了我們自定義的 GlideModule 的 registerComponents() 方法谍肤,只是啦租,我們的 GlideModule 的 registerComponents() 方法會(huì)覆蓋掉 OkHttpLibraryGlideModule 中的實(shí)現(xiàn)。(因?yàn)槲覀兊?GlideModule 的 registerComponents() 方法中調(diào)用的是 Registryreplace() 方法荒揣,會(huì)替換之前的效果篷角。)

如果不希望多此一舉,我們可以直接在自定義的 GlideModule 中使用 @Excludes 注解系任,并指定 OkHttpLibraryGlideModule 來直接排除該類恳蹲。這樣 GeneratedAppGlideModuleImpl 中的 registerComponents() 方法將只使用我們自定義的 GlideModule. 以下是排除之后生成的類中 registerComponents() 方法的實(shí)現(xiàn):

  @Override
  public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    appGlideModule.registerComponents(context, glide, registry);
  }

3虐块、總結(jié)

在本文中,我們通過介紹 Glide 的兩種常見的配置方式來分析了 Glide 的部分源碼實(shí)現(xiàn)嘉蕾。在這部分中贺奠,我們重點(diǎn)介紹了初始化 Glide 的并獲取 GlideModule 的過程,以及與圖片資源的時(shí)候相關(guān)的 ModelLoader 等的源碼错忱。了解這部分內(nèi)容是比較重要的敞嗡,因?yàn)樗鼈兪潜┞督o用戶的 API 接口,比較常用航背;并且對這些類簡單了解之后能夠不至于在隨后分析 Glide 整個(gè)加載流程的時(shí)候迷路。

這里我們對上面兩種配置方式中涉及到的類進(jìn)行一個(gè)分析棱貌。如下圖所示

Glide源碼

當(dāng)我們初始化 Glide 的時(shí)候會(huì)使用 Registryappend() 等一系列的方法構(gòu)建資源類型-加載方式-輸出類型 的一個(gè)映射玖媚,然后當(dāng)我們使用 Glide 進(jìn)行記載的時(shí)候,會(huì)先根據(jù)資源類型找到對應(yīng)的加載方式婚脱,然后使用該加載方式從指定的數(shù)據(jù)源中加載數(shù)據(jù)今魔,并將其轉(zhuǎn)換成指定的輸出類型。

以上面我們自定義圖片加載方式的過程為例障贸,這里我們自定義了一個(gè)資源類型 CacheImage错森,并通過自定義 GlideModule 指定了它的加載實(shí)現(xiàn)是我們自定義的 ImageLoader 類。然后篮洁,在我們自定義的 ImageLoader 中涩维,我們指定了獲取該資源的緩存的鍵的方式和從數(shù)據(jù)源中記載數(shù)據(jù)的具體實(shí)現(xiàn) HttpUrlFetcher。這樣袁波,當(dāng) Glide 要加載某個(gè) CacheImage 的時(shí)候瓦阐,會(huì)先使用該緩存的鍵嘗試從緩存中獲取,拿不到結(jié)果之后使用 HttpUrlFetcher 從網(wǎng)絡(luò)當(dāng)中獲取數(shù)據(jù)篷牌。從網(wǎng)絡(luò)中獲取數(shù)據(jù)的時(shí)候會(huì)得到 InputStream睡蟋,最后,再調(diào)用一個(gè)回調(diào)類枷颊,使用 BitmapFactory 從 InputStream 中獲取 Bitmap 并將其顯示到 ImageView 上面戳杀,這樣就完成了整個(gè)圖片加載的流程。

從上文的分析中夭苗,我們可以總結(jié)出 Glide 的幾個(gè)設(shè)計(jì)人性的地方:

  1. 使用代理類包裝自定義 GlideModule信卡,然后可以使用發(fā)射獲取該代理類,并通過調(diào)用代理類的方法來間接調(diào)用我們的 GlideModuel题造;
  2. 構(gòu)建資源類型-加載方式-輸出類型映射的時(shí)候使用工廠方法而不是通過某個(gè)類建立一對一映射坐求。

上面我們通過 Glide 的幾種配置方式簡單介紹了 Glide 的圖片加載流程。其實(shí)際的執(zhí)行過程遠(yuǎn)比我們上述過程更加復(fù)雜晌梨。在下文中我們會(huì)對 Glide 的圖片加載的主流程進(jìn)行分析桥嗤。歡迎繼續(xù)關(guān)注和閱讀须妻!


如果您喜歡我的文章,可以在以下平臺(tái)關(guān)注我:

更多文章:Gihub: Android-notes

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泛领,一起剝皮案震驚了整個(gè)濱河市荒吏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌渊鞋,老刑警劉巖绰更,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锡宋,居然都是意外死亡儡湾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門执俩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來徐钠,“玉大人,你說我怎么就攤上這事役首〕⒇ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵衡奥,是天一觀的道長爹袁。 經(jīng)常有香客問我,道長矮固,這世上最難降的妖魔是什么失息? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮档址,結(jié)果婚禮上根时,老公的妹妹穿的比我還像新娘。我一直安慰自己辰晕,他們只是感情好蛤迎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著含友,像睡著了一般替裆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窘问,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天辆童,我揣著相機(jī)與錄音,去河邊找鬼惠赫。 笑死把鉴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庭砍,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼场晶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了怠缸?” 一聲冷哼從身側(cè)響起诗轻,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揭北,沒想到半個(gè)月后扳炬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搔体,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年恨樟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疚俱。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡劝术,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出计螺,到底是詐尸還是另有隱情,我是刑警寧澤瞧壮,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布登馒,位于F島的核電站,受9級(jí)特大地震影響咆槽,放射性物質(zhì)發(fā)生泄漏陈轿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一秦忿、第九天 我趴在偏房一處隱蔽的房頂上張望麦射。 院中可真熱鬧,春花似錦灯谣、人聲如沸潜秋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峻呛。三九已至,卻和暖如春辜窑,著一層夾襖步出監(jiān)牢的瞬間钩述,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工穆碎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牙勘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓所禀,卻偏偏與公主長得像方面,于是被迫代替她去往敵國和親放钦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Glide筆記 一葡幸、簡介 在泰國舉行的谷歌開發(fā)者論壇上最筒,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫,作者是bu...
    AndroidMaster閱讀 3,898評(píng)論 0 27
  • 【Android 庫 Glide】 引用 Android圖片加載框架最全解析(一)蔚叨,Glide的基本用法Andro...
    Rtia閱讀 5,435評(píng)論 0 22
  • 7.1 壓縮圖片 一床蜘、基礎(chǔ)知識(shí) 1、圖片的格式 jpg:最常見的圖片格式蔑水。色彩還原度比較好邢锯,可以支持適當(dāng)壓縮后保持...
    AndroidMaster閱讀 2,515評(píng)論 0 13
  • 一、簡介 在泰國舉行的谷歌開發(fā)者論壇上搀别,谷歌為我們介紹了一個(gè)名叫Glide的圖片加載庫丹擎,作者是bumptech。這...
    天天大保建閱讀 7,474評(píng)論 2 28
  • 伴讀者 文 / 陳九諾 虔敬做事歇父,自有光輝蒂培。光輝在哪里?光輝在頭頂榜苫,在天上护戳;光輝在腳底,在地里垂睬。我這輩子或許什么...
    一塵逐日閱讀 146評(píng)論 0 1