毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选


我们在上篇OkHttp的时候说过这个Picasso,学名毕加索,是Square公司开源的一个Android图形缓存库,而且使用起来也是非常的简单,只要一行代码就轻松搞定了,你会问,为什么不介绍一下Glide?其实Glide我有时间也是会介绍的,刚好上篇我们用到了Picasso,所以就聊下这个,其实现在网上已经有很多关于Picasso的文章了,而Glide是Google的一位工程师根据Picasso做了很多优化的一个库,孰强孰弱,大家这块看看这个前辈的文章:

好的,我们就正式的开始今天的文章吧!

一.准备工作

图片缓存一直是个老掉牙的套路,即使众多老司机,也有不少在这里翻出,一言不合就大打出手的更加不计其数,我们在开发中要考虑很多种情况,比如

  • 在ListView中,我们要对Adapter进行一系列优化,而图片,要是没在视图中,我们应该取消这个不在视野中的图片加载,否则会导致很多情况发生
  • 图片太多,OOM,复杂的图片需要进行压缩,尽量减少内存的消耗
  • 图片缓存,本地缓存,二级硬盘缓存等

这些都是诸多需要考虑的东西,我们不可否认,虽然是有很多的解决方案,但都不是非常有效的,直到这些库的出现,乃至于优秀的库出现,比如Picasso,Glide之内的,我们先新建一个项目——Picasso

我们要想使用Picasso,需要配置他的依赖或者他的jar了

这里,我就集成他的依赖便于使用了,毕竟老司机使用的是Android Studio

compile 'com.squareup.picasso:picasso:(insert latest version)'

再加个网络权限

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

二.加载图片

这里,我们先从最简单的开始,Picasso和Glide类似,都很方便,一句话搞定,加载的话,哪里都会涉及,相信你也是会用的,所以我们从加载图片开始,首先,我们在xml中定义一个布局

    <Button
        android:id="@+id/btn_loading"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="加载图片" />

    <ImageView
        android:id="@+id/iv_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

紧接着,我们直接看他的点击事件

//下载图片
 btn_loading.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
            Picasso.with(MainActivity.this).load(url).into(iv_img);
        }
   });

可以看到,就一行代码,我的天哪,就是这么简单,而且你后面还可以增加一些属性,包括对图片翻转,定义大小,加载失败显示什么图片之类的,这个就详细的去看一下他的API文档就行,不是跟多,我们来看一下他运行的效果

OK,简单的加载我们就学会了

二.PicassoUtils

既然我们使用会了,现在应该去玩玩他的缓存了,这里我们直接封装成一个工具类岂不美哉?好的,我们开始封装,当然,我们也会封装我们OkHttp中说道的裁剪功能等:而且我们还会使用到我们上次封装的OkHttpUtils类

首先,我们封装与喜爱工具类,方法的作用也都有详细的注释

package com.lgl.picasso;

import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;
import com.squareup.picasso.Transformation;

/**
 * Picasso工具类
 * Created by LGL on 2016/6/23.
 */
public class PicassoUtils {

    /**
     * 指定大小加载图片
     *
     * @param mContext   上下文
     * @param path       图片路径
     * @param width      宽
     * @param height     高
     * @param mImageView 控件
     */
    public static void loadImageViewSize(Context mContext, String path, int width, int height, ImageView mImageView) {
        Picasso.with(mContext).load(path).resize(width, height).centerCrop().into(mImageView);
    }

    /**
     * 加载有默认图片
     *
     * @param mContext   上下文
     * @param path       图片路径
     * @param resId      默认图片资源
     * @param mImageView 控件
     */
    public static void loadImageViewHolder(Context mContext, String path, int resId, ImageView mImageView) {
        Picasso.with(mContext).load(path).fit().placeholder(resId).into(mImageView);
    }

    /**
     * 裁剪图片
     *
     * @param mContext   上下文
     * @param path       图片路径
     * @param mImageView 控件
     */
    public static void loadImageViewCrop(Context mContext, String path, ImageView mImageView) {
        Picasso.with(mContext).load(path).transform(new CropImageView()).into(mImageView);
    }

    /**
     * 自定义图片裁剪
     */
    public static class CropImageView implements Transformation {

        @Override
        public Bitmap transform(Bitmap source) {
            int size = Math.min(source.getWidth(), source.getHeight());
            int x = (source.getWidth() - size) / 2;
            int y = (source.getHeight() - size) / 2;

            Bitmap newBitmap = Bitmap.createBitmap(source, x, y, size, size);

            if (newBitmap != null) {
                //内存回收
                source.recycle();
            }
            return newBitmap;
        }

        @Override
        public String key() {

            return "lgl";
        }
    }
}

三.微信精选

既然工具类写完了,我们就要开工了,我们这次做的是一个微信精选,接口我是从聚合数据拿的

 //微信精选接口
 private String wechat_url = "http://v.juhe.cn/weixin/query?key=78f723dccf85aea324a3cf0daac97f35";

我们在xml中定义一个listview的控件

 <ListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

然后我们就可以去解析这个接口,我们使用的是上节封装的OkHttp

 OkHttpUtils okHttp = OkHttpUtils.getInstance();
        okHttp.syncJsonStringByURL(wechat_url, new OkHttpUtils.FuncJsonString() {
            @Override
            public void onResponse(String result) {
                Log.i("json", result);
                getJson(result);
            }
        });

如果你还不知道怎么去使用OkHttp的话,可以去看我的博文

OK,我们解析得到json,现在就要根据json去写个实体类了

package com.lgl.picasso;

/**
 * 微信精选
 *
 * @author LGL
 */
public class WechatBean {

    private String url;
    private String title;
    private String type;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "WechatBean [url=" + url + ", title=" + title + ", type=" + type
                + "]";
    }
}

做完实体类,我们有数据封装方式了,那就直接去写Adapter吧

package com.lgl.picasso;

import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * 数据源
 *
 * @author LGL
 */
public class WechatAdapter extends BaseAdapter {

    private Context mContext;
    private LayoutInflater inflater;
    private List<WechatBean> mList;
    private WechatBean bean;

    public WechatAdapter(Context mContext, List<WechatBean> mList) {
        this.mContext = mContext;
        this.mList = mList;
        inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return mList.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHoldwe vHoldwe = null;
        if (convertView == null) {
            vHoldwe = new ViewHoldwe();
            convertView = inflater.inflate(R.layout.wechatist_item, null);
            vHoldwe.iv_url = (ImageView) convertView
                    .findViewById(R.id.iv_url);
            vHoldwe.tv_title = (TextView) convertView
                    .findViewById(R.id.tv_title);
            vHoldwe.tv_type = (TextView) convertView.findViewById(R.id.tv_type);
            convertView.setTag(vHoldwe);
        } else {
            vHoldwe = (ViewHoldwe) convertView.getTag();
        }

        bean = mList.get(position);
        vHoldwe.tv_title.setText(bean.getTitle());
        vHoldwe.tv_type.setText(bean.getType());

        if(!TextUtils.isEmpty(bean.getUrl())){
            PicassoUtils.loadImageViewSize(mContext, bean.getUrl(),150,100, vHoldwe.iv_url);
        }else{
            vHoldwe.iv_url.setImageResource(R.mipmap.ic_launcher);
        }

        return convertView;
    }

    class ViewHoldwe {
        private ImageView iv_url;
        private TextView tv_title;
        private TextView tv_type;
    }

}

Adapter算是老生常谈的问题了,我们这里使用到了我们封装好的Picasso工具类,到这里我们就可以去看一下怎么解析json了

/**
     * 解析Json
     *
     * @param json
     */
    private void getJson(String json) {
        try {
            JSONObject jsonObject = new JSONObject(json);
            JSONObject jsonresult = jsonObject.getJSONObject("result");
            JSONArray jArray = jsonresult.getJSONArray("list");

            for (int i = 0; i < jArray.length(); i++) {
                JSONObject jb = (JSONObject) jArray.get(i);
                WechatBean bean = new WechatBean();
                bean.setTitle(jb.getString("title"));
                bean.setType(jb.getString("source"));
                bean.setUrl(jb.getString("firstImg"));
                mList.add(bean);

                //存起来
                urlList.add(jb.getString("url"));
                titleList.add(jb.getString("title"));
            }
            adapter = new WechatAdapter(this, mList);
            mListView.setAdapter(adapter);

        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

解析json还是比较简单的,如果不会,可以移步我的博文

好的,到这里我们初步的解析算是OK了,我们来看下效果

四.缓存优化

这里做一些简单的处理就好了,首先,我们滑动视图,如果我们看不见的视图我们可以不加载,这样慢慢的加载,对我们app提升还是很有帮助的,所以我们要设置监听

 //监听
  mListView.setOnScrollListener(new ListScroller());

关于它的回调

 /**
     * 滚动监听
     */
    public class ListScroller implements AbsListView.OnScrollListener {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            final Picasso picasso = Picasso.with(MainActivity.this);
            if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
                //重置
                picasso.resumeTag(MainActivity.this);
            } else {
                //暂停
                picasso.pauseTag(MainActivity.this);
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

        }
    }

当然,还有我们既然是一个新闻客户端,怎么的,也要可以看新闻才对,对吧,所以我们新建一个WebViewActivity,首先传值跳转

        //监听
        mListView.setOnScrollListener(new ListScroller());

        //跳转
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent i = new Intent(MainActivity.this, WebViewActivity.class);
                i.putExtra("title", titleList.get(position));
                i.putExtra("url", urlList.get(position));
                startActivity(i);
            }
        });

而WebViewActivity的代码就比较少了

package com.lgl.picasso;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebView;

/**
 * 客户端
 * Created by LGL on 2016/6/23.
 */
public class WebViewActivity extends AppCompatActivity{

    private WebView mWebView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);

        mWebView = (WebView) findViewById(R.id.mWebView);

        Intent i = getIntent();

        getSupportActionBar().setTitle(i.getStringExtra("title"));
        mWebView.loadUrl(i.getStringExtra("url"));

        //本地显示
        mWebView.setWebViewClient(new android.webkit.WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

                view.loadUrl(url);

                return true;
            }
        });
    }
}

哦,对了,别忘记了注册

 <activity android:name=".WebViewActivity"/>

到这里,整个项目下来算是做完了,我们可以运行一下

到此,我们的博文算是结束了,当然,我还有很多知识没讲,需要大家一起去研究

如果对我活着Android技术感兴趣,欢迎加群:555974449

Demo下载:http://download.csdn.net/detail/qq_26787115/9557996

毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选的更多相关文章

  1. picasso_强大的Android图片下载缓存库

    tag: android pic skill date: 2016/07/09 title: picasso-强大的Android图片下载缓存库 [本文转载自:泡在网上的日子 参考:http://bl ...

  2. picasso-强大的Android图片下载缓存库

    编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! pica ...

  3. android开源项目:图片下载缓存库picasso

    picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能. picasso有如下特性: 在a ...

  4. Android 图片加载库Glide 实战(二),占位符,缓存,转换自签名高级实战

    http://blog.csdn.net/sk719887916/article/details/40073747 请尊重原创 : skay <Android 图片加载库Glide 实战(一), ...

  5. 如何使用picasso 对Android图片下载缓存

    相比较其他,picasso的图片缓存更加简单一些,他只需要一行代码就可以表述:导入相关jar包 Picasso.with(context).load("图片路径").into(Im ...

  6. fackbook的Fresco (FaceBook推出的Android图片加载库-Fresco)

    [Android开发经验]FaceBook推出的Android图片加载库-Fresco   欢迎关注ndroid-tech-frontier开源项目,定期翻译国外Android优质的技术.开源库.软件 ...

  7. FaceBook推出的Android图片加载库-Fresco

    FaceBook推出的Android图片加载库-Fresco 原文链接:Introducing Fresco: A new image library for Android 译者 : ZhaoKai ...

  8. Android图片加载库的理解

    前言     这是“基础自测”系列的第三篇文章,以Android开发需要熟悉的20个技术点为切入点,本篇重点讲讲Android中的ImageLoader这个库的一些理解,在Android上最让人头疼是 ...

  9. android图片加载库Glide

    什么是Glide? Glide是一个加载图片的库,作者是bumptech,它是在泰国举行的google 开发者论坛上google为我们介绍的,这个库被广泛的运用在google的开源项目中. Glide ...

随机推荐

  1. sb error

    width: $("#StudentManagement").parent().width(), height: $("#StudentManagement") ...

  2. SVN提交时显示:Path is not a working copy directory

    说明你地址没有checkout啊 先checkout,才能add和commi. 要是在一个已有的项目出现这个错误,就是包含这个地址的文件夹没添加进去,去上一层再试一次. 总之,养成在项目根目录提交的习 ...

  3. day0203 XML 学习笔记

    day02, 03 1. xml语言和作用 2. xml语法详解 2.1 xml 语法声明 2.1.1 encoding 属性 2.1.2 standalone 属性 2.2 xml 元素(Eleme ...

  4. 聊聊LightProbe原理实现以及对LightProbe数据的修改

    0x00 前言 最近工作比较忙,所以文章已经很久没有更新了.这篇小文的主题也是在出差的高铁上想到,因为最近和一些朋友聊天,发现他们中很多人的项目中都使用了多个实时光源.细问之下主要是某些物体,例如角色 ...

  5. Docker基本架构

    Docker 采用了 C/S架构,包括客户端和服务端. Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建.运行.分发容器). 客户端和服务端既可以运行在一个机器上,也可通 ...

  6. Bootstrap3 排版-缩略语

    当鼠标悬停在缩写和缩写词上时就会显示完整内容,Bootstrap 实现了对 HTML 的 <abbr> 元素的增强样式.缩略语元素带有 title 属性,外观表现为带有较浅的虚线框,鼠标移 ...

  7. move_uploaded_file的failed to open stream错误处理

    PHP的基本语法学习的差不多了,现在开始学习PHP的文件上传功能实现了.功能中使用到了move_uploaded_file方法,运行时报错: failed to open stream. 经过查资料, ...

  8. 20160218.CCPP体系详解(0028天)

    程序片段(01):加法.c 内容概要:字符串计算表达式 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <st ...

  9. 20160213.CCPP体系详解(0023天)

    程序片段(01):全排列.c 内容概要:全排列密码库 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <std ...

  10. Angular2入坑指南

    序 对后端开发来说,前端是神秘的,眼花缭乱的技术,繁多的框架,出名的不出名的好几百种,看是"繁荣",其实显得杂乱无章,但是我们在做开发的时候,技术选型还是主流的那么几个:浅析ang ...