ImageViewEx控件介绍

https://github.com/wasabeef/glide-transformations

 


最近在整理项目中的一些代码,以备即将开展的新项目中使用,刚刚整理到一个图片加载的 lib,用起来非常的简单,和 picasso 或者谷歌的 Volley 等都一样,只需要一行代码就能完成图片加载的逻辑。

项目效果:

二、使用

先给出使用方法:首先在布局文件中加入如下代码:

[XML] 查看源文件 复制代码

?

1

2

3

4

5

6

<mrfu.imageviewex.lib.ImageViewEx

    android:id="@+id/imageview"

    android:layout_width="match_parent"

    android:layout_height="200dp"

    android:layout_below="@+id/toolbar"

    android:scaleType="centerCrop" />

 

如果是要使用圆形或者圆角的图片,只需要将 ImageViewEx 改成 RoundImageView 就可以了。

Java 代码中,这样写就可以了

[Java] 查看源文件 复制代码

?

1

2

3

4

5

6

7

ImageViewEx imageviewex = (ImageViewEx)findViewById(R.id.imageview);

RoundImageView roundimageview1 = (RoundImageView)findViewById(R.id.roundimageview1);

RoundImageView roundimageview2 = (RoundImageView)findViewById(R.id.roundimageview2);

imageviewex.loadImage("http://f.hiphotos.baidu.com/image/pic/item/ae51f3deb48f8c5471a15c2e38292df5e0fe7f45.jpg");

roundimageview1.loadImage("http://f.hiphotos.baidu.com/image/pic/item/ae51f3deb48f8c5471a15c2e38292df5e0fe7f45.jpg");

roundimageview2.setConer(10, 10);//设置圆角图片

roundimageview2.loadImage("http://f.hiphotos.baidu.com/image/pic/item/ae51f3deb48f8c5471a15c2e38292df5e0fe7f45.jpg");


三、 原理

先给出类关系图

使用方式非常简单,现在大概来分析一下这个框架的原理:

框架的加载方式主要还是通过 http 请求的 get 方式拿到图片,然后将其保存在 SD 卡中,将 SD 卡中的图片转化为 Bitmap 对象,通过 LruMemoryCache 缓存方式存到内存中。并将其加载到对应 View 上去。

主要类就是 ImageViewEx 和 ImageLoader 了

1、 ImageViewEx.java

这个类的主要功能就是设置加载时的默认图片,调用ImageLoader 类的loadImageAsync进行加载图片,对加载完成后的回调进行处理。都在loadImage(url)中体现了:

[Java] 查看源文件 复制代码

?

01

02

03

04

05

06

07

08

09

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

public void loadImage(String url) {

    mUrl = url;

    setImageBitmap(null);

 

    //设置加载时的默认图片

    if (defaultDrawable != null) {

        setImageDrawable(defaultDrawable);

    } else if (defaultImg != null) {

        setImageBitmap(defaultImg);

    } else {

        setImageDrawable(defaultImage);

    }

    //调用ImageLoader,进行图片加载

    ImageLoader.ImageRequest request = new ImageLoader.ImageRequest(url, this);

    ImageLoader.get().loadImageAsync(request, mHttpCallback);

}

 

protected void toMeasure(Bitmap bitmap){};

 

AbsHttpCallback mHttpCallback = new AbsHttpCallback() {

    @Override

    public void onSuccess(final ImageRequest request, final Bitmap bitmap) {

        if(!request.url.equals(mUrl)) {

            return ;

        }

        toMeasure(bitmap);

 

        final ImageView iv = (ImageView)request.cookie;

        if(request.inMemory) {

            iv.setImageBitmap(bitmap);

            return ;

        }

        //设置动画

        handler.post(new Runnable() {

            @Override

            public void run() {

                if(request.url.equals(mUrl)) {

                    setImageWithAnimation(iv, bitmap);

                }

            }

        });

    }


2、 ImageLoader.java

使用最大运行内存的十六分之一作为 LruMemoryCache 的缓存大小,如果超过了这个大小,系统会自动将其释放掉。

在加载的过程中,线程池可以开启的最多任务数为 MAX_BLOCK_QUEUE_SIZE 个,balanceTasks()这个方法,保证了队列的最大任务数:

[Java] 查看源文件 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

/**

 * balance tasks

 */

private void balanceTasks() {

    BlockingQueue<Runnable> queue = mExecutorPool.getQueue();

    if (queue == null) {

        return ;

    }

    int poolSize = queue.size();

    if (poolSize > MAX_BLOCK_QUEUE_SIZE) { //保留队尾MAX_BLOCK_QUEUE_SIZE个队列其他清理掉

        int keep = poolSize - MAX_BLOCK_QUEUE_SIZE;

        List<Runnable> list = new ArrayList<Runnable>();

        int i = 0;

        while (queue.size() > 0) {

            i++;

            Runnable r = queue.remove();

            if (i >= keep) {

                list.add(r);

            } else {

                LocalTask task = (LocalTask) r;

                mTaskQueue.remove(task.httpRequest.url);

            }

        }

        queue.clear();

        queue.addAll(list);

    }

}

 

在内部类 LocalTask 中进行加载的逻辑,主要看 run() 方法,先根据 url 拿到 SD 卡中的存储路径pathName,将 pathName 解析成 Bitmap 对象,如果不为 null 表示 SD 卡中有该图片,直接取 SD 卡中的图片,否则删除这个文件,并通过 HttpRequestGet 去下载该图片,下载完成后会回调 requestFinished 方法,并调用 notifySuccess 方法,注意,不管成功还是失败,都需要将其从任务队列 mTaskQueue 中删除。

[Java] 查看源文件 复制代码

?

01

02

03

04

05

06

07

08

09

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

/**

 * local task

 *

 */

private class LocalTask implements Runnable, HttpGetProgressCallback {

    private ImageRequest httpRequest;

    private AbsHttpCallback callback;

    public LocalTask(ImageRequest request, AbsHttpCallback callback) {

        this.httpRequest = request;

        this.callback = callback;

    }

    @Override

    public void run() {

        String pathName = FileStore.cachePathForKey(httpRequest.url);

        if (!TextUtils.isEmpty(pathName)) {

            Bitmap  bitmap = decodeBitmap(pathName);

            if(bitmap != null) {

                notifySuccess(httpRequest, callback, bitmap);

                return ;

            } else {

                new File(pathName).delete();

            }

        }

        callback.onStart(httpRequest);

        HttpRequestGet httpGet = new HttpRequestGet(httpRequest.url, this);

        httpGet.run();

    }

    @Override

    public void requestFinished(String url, String pathName) {

        Bitmap bitmap = decodeBitmap(pathName);

        if(bitmap != null) {

            notifySuccess(httpRequest, callback, bitmap);

        }

    }

    @Override

    public void requestFailed(String url, String errorStr) {

        notifyFailure(httpRequest, callback, HttpErrorResult.HTTP_GET_FAIL);

    }

 

    @Override

    public void progressPublish(String url, int progress) {

        callback.onProgress(httpRequest, progress);

    }

 

}

 

[Java] 查看源文件 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

/**

 * notify success tasks

 * @param httpRequest

 * @param callback

 */

private void notifySuccess(ImageRequest httpRequest, AbsHttpCallback callback, Bitmap bitmap) {

    mBitmapCache.put(httpRequest.url, bitmap);

    Set<ItemTask> set = mTaskQueue.get(httpRequest.url);

    if(set != null){

        for(ItemTask task : set){

            task.callback.onSuccess(task.httpRequest, bitmap);

        }

        set.clear();

        mTaskQueue.remove(httpRequest.url);

    }

}

private void notifyFailure(ImageRequest httpRequest, AbsHttpCallback callback, HttpErrorResult error) {

    Set<ItemTask> set = mTaskQueue.get(httpRequest.url);

    if(set != null){

        for(ItemTask task : set){

            task.callback.onFailure(task.httpRequest, HttpErrorResult.HTTP_GET_FAIL);

        }

        set.clear();

        mTaskQueue.remove(httpRequest.url);

    }

}


3、 HttpRequestGet.java

get 请求成功后,创建文件路径,将请求到的数据存储到文件中,通知回调成功或者失败的结果。

4、 RoundImageView.java

这个类就比较简单了,继承自 ImageViewEx,功能是 设置圆形图片,主要就是重写了 onDraw(canvas); 方法,在这个方法里调用了 Canvas 的 drawRoundRect 方法。注意,如果要设置成圆角图片 则需要调用 setConer(x,y); 如果不调用表示圆形图片:

[Java] 查看源文件 复制代码

?

01

02

03

04

05

06

07

08

09

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

@Override 

protected void onDraw(Canvas canvas) { 

    Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),

            Bitmap.Config.ARGB_8888);

    Canvas c = new Canvas(bitmap);

    Paint paint = new Paint(1);

    paint.setColor(Color.BLACK);

    if (x != 0 && y != 0) {

        c.drawRoundRect(

                new RectF(0.0F, 0.0F, getWidth(), getHeight()),

                x, y, paint);

    }else {

        c.drawRoundRect(

                new RectF(0.0F, 0.0F, getWidth(), getHeight()),

                getWidth()/2, getHeight()/2, paint);

    }

    Paint paint0 = new Paint();

    new PorterDuffXfermode(

            PorterDuff.Mode.DST_IN);

    paint0.setFilterBitmap(false);

            paint0.setXfermode(new PorterDuffXfermode(

            PorterDuff.Mode.DST_IN));

    try{

        Drawable drawable = getDrawable();

        if (drawable != null) {

            int saveCount = canvas.saveLayer(0.0F, 0.0F, getWidth(),

                    getHeight(), null, 31);

            drawable.setBounds(0, 0, getWidth(), getHeight());

            drawable.draw(canvas);

            canvas.drawBitmap(bitmap, 0.0F, 0.0F, paint0);

            canvas.restoreToCount(saveCount);

        }

    }catch(Exception e){

        e.printStackTrace();

    }catch(Throwable t){

        t.printStackTrace();

    }

}

 

基本的就是这样,框架其实很简单,将其抽取出来作为一个框架来用的话,还是很方便的。对了如果要显示下载进度,只需要调用 HttpGetProgressCallback 接口就可以了,这个可以自己去封装。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大伟伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值