Android - 圖片處理之Glide4.0版本

老婆保佑刑桑,代碼無BUG

前言

一般項目我都會使用Glide作為我的圖片加載框架蝇刀,他和Picasso ,真的很像树枫,郭大神早就分析過了直焙,很詳細,這里也就簡單做個記錄砂轻。小白白一枚奔誓,學(xué)習(xí)路上

Android圖片加載框架最全解析(一),Glide的基本用法

Android圖片加載框架最全解析(二)搔涝,從源碼的角度理解Glide的執(zhí)行流程

Android圖片加載框架最全解析(三)厨喂,深入探究Glide的緩存機制

Android圖片加載框架最全解析(四),玩轉(zhuǎn)Glide的回調(diào)與監(jiān)聽

Android圖片加載框架最全解析(五)庄呈,Glide強大的圖片變換功能

Android圖片加載框架最全解析(六)蜕煌,探究Glide的自定義模塊功能

Android圖片加載框架最全解析(七),實現(xiàn)帶進度的Glide圖片加載功能

Android圖片加載框架最全解析(八)诬留,帶你全面了解Glide 4的用法


目錄

  • 一:GitHub
  • 二:下載使用
      1. Gradle
      1. Android SDK 要求
      • 解決方案
    • 3.權(quán)限
  • 二:apply && RequestOptions
  • 三:API 介紹
  • 四: 補充說明
      1. diskCacheStrategy參數(shù)補充
      1. asBitmap()注意坑
      1. submit()
      1. transforms
      • (1) 轉(zhuǎn)成黑白
      • (2) 高斯模糊
      • (3) 圓形
      • (4 ) 圓角
  • 5.Generated API

一:GitHub

bumptech/glide

二:下載使用

點擊斜纪,跳轉(zhuǎn)到官網(wǎng)贫母,介紹很詳細

1. Gradle

repositories {
  mavenCentral()
  maven { url 'https://maven.google.com' }
}
dependencies {
    compile 'com.github.bumptech.glide:glide:4.4.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0'
}

2. Android SDK 要求

  • Min Sdk Version - 使用 Glide 需要 min SDK 版本 API 14 (Ice Cream Sandwich) 或更高。
  • Compile Sdk Version - Glide 必須使用 API 26 (Oreo) 或更高版本的 SDK 來編譯盒刚。
  • Support Library Version - Glide 使用的支持庫版本為 27腺劣。

否則會出現(xiàn)如下異常


解決方案

dependencies {
    implementation 'com.android.support:appcompat-v7:27.0.2' //這個版本的就可以了
    implementation 'com.github.bumptech.glide:glide:4.4.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0'
}

3.權(quán)限

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

二:apply && RequestOptions

4.0之前最常用的方式,當(dāng)然現(xiàn)在也是哈

Glide.with(this)
     .load(url)
     .into(img);

4.0之后伪冰,有一個新的東西

   Glide.with(this)
                .load(url)
//                .apply(RequestOptions options)
                .into(img);

比如 我們加載占位圖和錯誤圖

RequestOptions options = new RequestOptions()
        .error(R.drawable.error)
        .placeholder(R.drawable.loading);
Glide.with(this)
     .load(url)
     .apply(options)
     .into(imageView);

小伙伴們沒看錯誓酒,這樣的方式,擺脫了贮聂,以前鏈?zhǔn)綄懛ㄖ锌扛蹋珿lide很長很長,現(xiàn)在的話吓懈,我們可以傳入一個RequestOptions歼冰,對象,就有小伙伴問了耻警,有啥用隔嫡,我覺得,比較容易封裝甘穿,

例如

public class GlideUtil {

    public static void load(Context context,
                            String url,
                            ImageView imageView,
                            RequestOptions options) {
        Glide.with(context)
             .load(url)
             .apply(options)
             .into(imageView);
    }
}

三:API 介紹

API 介紹
占位符(Placeholder) 當(dāng)請求正在執(zhí)行時被展示的 Drawable
錯誤符(Error) 請求永久性失敗時展示
后備回調(diào)符(Fallback) 在請求的url/model為 null 時展示
override 指定了一個圖片的尺寸,Target.SIZE_ORIGINAL加載圖片的原始尺寸
skipMemoryCache(true) 禁用內(nèi)存緩存功能
diskCacheStrategy(DiskCacheStrategy.NONE) 禁用硬盤緩存功能,參數(shù)列表如下 四(1)
asBitmap() 只允許加載靜態(tài)圖片,腮恩。如果傳入的是GIF圖,會展示GIF圖的第一幀
asFile() 指定文件格式 注意事項 如下 四(2)
asDrawable() 指定Drawable格式
submit() 使用如下四(3)
transforms 圖片變換,Glide 默認有3個温兼,如下四(4)

四: 補充說明

1. diskCacheStrategy參數(shù)補充

參數(shù) 說明
DiskCacheStrategy.NONE 表示不緩存任何內(nèi)容秸滴。
DiskCacheStrategy.DATA 表示只緩存原始圖片。
DiskCacheStrategy.RESOURCE 表示只緩存轉(zhuǎn)換過后的圖片募判。
DiskCacheStrategy.ALL 表示既緩存原始圖片荡含,也緩存轉(zhuǎn)換過后的圖片。
DiskCacheStrategy.AUTOMATIC 表示讓Glide根據(jù)圖片資源智能地選擇使用哪一種緩存策略(默認選項)届垫。

2. asBitmap()注意坑

熟悉Glide 3的朋友對asBitmap()方法肯定不會陌生對吧释液?但是千萬不要覺得這里就沒有陷阱了,在Glide 3中的語法是先load()再asBitmap()的装处,而在Glide 4中是先asBitmap()再load()的误债。乍一看可能分辨不出來有什么區(qū)別,但如果你寫錯了順序就肯定會報錯了

3. submit()

通過如下代碼妄迁,可以獲取到找前,下載好的圖片放在哪,可以看到 都在cache

   new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    File file = Glide.with(MainActivity.this)
                            .asFile()
                            .load(url)
                            .submit()
                            .get();
                    Log.e("Tag", "path-->" + file.getPath());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }).start();


 E/Tag: path-->/data/user/0/com.allens.glidedemo/cache/image_manager_disk_cache/309df01e6362ddc8939a4e3c549e8276dffb0446a89f2facee371909301fe76a.0

4. transforms

內(nèi)置有這3個

RequestOptions options = new RequestOptions()
        .centerCrop();

RequestOptions options = new RequestOptions()
        .fitCenter();

RequestOptions options = new RequestOptions()
        .circleCrop();//圓形

一般我們還會自己去定義判族,以下是常用的3種轉(zhuǎn)換

使用起來也很簡單

   RequestOptions options = new RequestOptions()
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.NONE);
                //圓形
               .transforms(new CircleTransform(mContext,2, Color.DKGRAY))//外圈寬度躺盛,外圈顏色
                //黑白
               .transforms(new BlackWhiteTransformation());
               //高斯模糊 范圍在 0 -- 25 越大模糊程度越高
               .transforms(new BlurTransformation(mContext, 25)); // (0 < r <= 25)
                //可以使用多種
               .transforms(new BlurTransformation(mContext, 25),new CircleTransform(mContext,2, Color.DKGRAY))

(1) 轉(zhuǎn)成黑白

package com.allens.lib_glide.Transformation;

import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.support.annotation.NonNull;
import android.view.animation.Transformation;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.security.MessageDigest;

/**
 * 描述:
 * <p> 黑白
 * Created by allens on 2018/1/8.
 */

public class BlackWhiteTransformation extends BitmapTransformation {
    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        return convertToBlackWhite(toTransform);
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest) {

    }

    private Bitmap convertToBlackWhite(Bitmap bmp) {
        int width = bmp.getWidth(); // 獲取位圖的寬
        int height = bmp.getHeight(); // 獲取位圖的高
        int[] pixels = new int[width * height]; // 通過位圖的大小創(chuàng)建像素點數(shù)組

        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        int alpha = 0xFF << 24;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int grey = pixels[width * i + j];

                //分離三原色
                int red = ((grey & 0x00FF0000) >> 16);
                int green = ((grey & 0x0000FF00) >> 8);
                int blue = (grey & 0x000000FF);

                //轉(zhuǎn)化成灰度像素
                grey = (int) (red * 0.3 + green * 0.59 + blue * 0.11);
                grey = alpha | (grey << 16) | (grey << 8) | grey;
                pixels[width * i + j] = grey;
            }
        }
        //新建圖片
        Bitmap newBmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        //設(shè)置圖片數(shù)據(jù)
        newBmp.setPixels(pixels, 0, width, 0, 0, width, height);

        Bitmap resizeBmp = ThumbnailUtils.extractThumbnail(newBmp, 380, 460);
        return resizeBmp;
    }
}

(2)高斯模糊

package com.allens.lib_glide.Transformation;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RSRuntimeException;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.support.annotation.NonNull;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.security.MessageDigest;

/**
 * 描述: 高斯模糊
 * <p>
 * Created by allens on 2018/1/8.
 */

public class BlurTransformation extends BitmapTransformation {


    private Context context;

    private float blurRadius;

    public BlurTransformation(Context context, float blurRadius) {
        this.context = context;
        this.blurRadius = blurRadius;
    }

    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        return blurBitmap(context, toTransform, blurRadius, outWidth, outHeight);
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest) {

    }

    /**
     * @param context   上下文對象
     * @param image     需要模糊的圖片
     * @param outWidth  輸入出的寬度
     * @param outHeight 輸出的高度
     * @return 模糊處理后的Bitmap
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    public Bitmap blurBitmap(Context context, Bitmap image, float blurRadius, int outWidth, int outHeight) {
        // 將縮小后的圖片做為預(yù)渲染的圖片
        Bitmap inputBitmap = Bitmap.createScaledBitmap(image, outWidth, outHeight, false);
        // 創(chuàng)建一張渲染后的輸出圖片
        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
        // 創(chuàng)建RenderScript內(nèi)核對象
        RenderScript rs = RenderScript.create(context);
        // 創(chuàng)建一個模糊效果的RenderScript的工具對象
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        // 由于RenderScript并沒有使用VM來分配內(nèi)存,所以需要使用Allocation類來創(chuàng)建和分配內(nèi)存空間
        // 創(chuàng)建Allocation對象的時候其實內(nèi)存是空的,需要使用copyTo()將數(shù)據(jù)填充進去
        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
        // 設(shè)置渲染的模糊程度, 25f是最大模糊度
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            blurScript.setRadius(blurRadius);
        }
        // 設(shè)置blurScript對象的輸入內(nèi)存
        blurScript.setInput(tmpIn);
        // 將輸出數(shù)據(jù)保存到輸出內(nèi)存中
        blurScript.forEach(tmpOut);
        // 將數(shù)據(jù)填充到Allocation中
        tmpOut.copyTo(outputBitmap);
        return outputBitmap;
    }

}

(3) 圓形

package com.allens.lib_glide.Transformation;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.NonNull;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.security.MessageDigest;

/**
 * 描述:
 * <p> 圓形
 * Created by allens on 2018/1/8.
 */

public class CircleTransform extends BitmapTransformation {
    private Paint mBorderPaint;
    private float mBorderWidth;

    public CircleTransform(Context context) {
        super(context);
    }

    public CircleTransform(Context context, int borderWidth, int borderColor) {
        super(context);
        mBorderWidth = Resources.getSystem().getDisplayMetrics().density * borderWidth;
        mBorderPaint = new Paint();
        mBorderPaint.setDither(true);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(borderColor);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setStrokeWidth(mBorderWidth);
    }

    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest) {

    }

    private Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) {
            return null;
        }
        int size = (int) (Math.min(source.getWidth(), source.getHeight()) - (mBorderWidth / 2));
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
        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);
        if (mBorderPaint != null) {
            float borderRadius = r - mBorderWidth / 2;
            canvas.drawCircle(r, r, borderRadius, mBorderPaint);
        }
        return result;
    }
}

4.0 圓角

package com.starot.spark.transformation;


import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.NonNull;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

import java.security.MessageDigest;

/**
 * 描述:
 * <p> 圓形
 *
 * @author allens
 * @date 2018/1/8
 */

public class CircleTransform extends BitmapTransformation {
    private Paint mBorderPaint;
    private float mBorderWidth;

    public CircleTransform(Context context) {
        super(context);
    }

    public CircleTransform(Context context, int borderWidth, int borderColor) {
        super(context);
        mBorderWidth = Resources.getSystem().getDisplayMetrics().density * borderWidth;
        mBorderPaint = new Paint();
        mBorderPaint.setDither(true);
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(borderColor);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setStrokeWidth(mBorderWidth);
    }

    @Override
    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest) {

    }

    private Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) {
            return null;
        }
        int size = (int) (Math.min(source.getWidth(), source.getHeight()) - (mBorderWidth / 2));
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
        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);
        if (mBorderPaint != null) {
            float borderRadius = r - mBorderWidth / 2;
            canvas.drawCircle(r, r, borderRadius, mBorderPaint);
        }
        return result;
    }
}

5.Generated API

如果4.0用的不爽,就想使用3.0版本的那種鏈?zhǔn)綄懛?將Glide 關(guān)鍵字改成
GlideApp即可

GlideApp.with(this)
        .load(url)
        .placeholder(R.drawable.loading)
        .error(R.drawable.error)
        .skipMemoryCache(true)
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        .override(Target.SIZE_ORIGINAL)
        .circleCrop()
        .into(imageView);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末形帮,一起剝皮案震驚了整個濱河市槽惫,隨后出現(xiàn)的幾起案子周叮,更是在濱河造成了極大的恐慌,老刑警劉巖界斜,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仿耽,死亡現(xiàn)場離奇詭異,居然都是意外死亡各薇,警方通過查閱死者的電腦和手機项贺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來峭判,“玉大人开缎,你說我怎么就攤上這事×煮Γ” “怎么了奕删?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疗认。 經(jīng)常有香客問我完残,道長,這世上最難降的妖魔是什么横漏? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任谨设,我火速辦了婚禮,結(jié)果婚禮上缎浇,老公的妹妹穿的比我還像新娘扎拣。我一直安慰自己,他們只是感情好华畏,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著尊蚁,像睡著了一般亡笑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上横朋,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天仑乌,我揣著相機與錄音,去河邊找鬼琴锭。 笑死晰甚,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的决帖。 我是一名探鬼主播厕九,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼地回!你這毒婦竟也來了扁远?” 一聲冷哼從身側(cè)響起俊鱼,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畅买,沒想到半個月后并闲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡谷羞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年帝火,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湃缎。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡犀填,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雁歌,到底是詐尸還是另有隱情宏浩,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布靠瞎,位于F島的核電站比庄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏乏盐。R本人自食惡果不足惜佳窑,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望父能。 院中可真熱鬧神凑,春花似錦、人聲如沸何吝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爱榕。三九已至瓣喊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間黔酥,已是汗流浹背藻三。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跪者,地道東北人棵帽。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像渣玲,于是被迫代替她去往敵國和親逗概。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,104評論 25 707
  • afinalAfinal是一個android的ioc忘衍,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評論 2 45
  • 一.榜單介紹 排行榜包括四大類: 單一框架:僅提供路由仗谆、網(wǎng)絡(luò)層指巡、UI層、通信層或其他單一功能的框架 混合開發(fā)框架:...
    偉子男閱讀 5,243評論 0 161
  • 到南開隶垮,N次自我介紹時的對話 “同學(xué)藻雪,你是哪的人?” “我是衡水的狸吞,你知道嗎勉耀?” “知道,衡水中學(xué)多厲害蹋偏,你是衡中...
    以一圣真閱讀 449評論 0 3
  • 中國的教育不是差便斥,而是很差,非常差威始。
    紅樓坐隱閱讀 104評論 0 0