毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
毕加索的艺术——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实现微信精选的更多相关文章
- picasso_强大的Android图片下载缓存库
tag: android pic skill date: 2016/07/09 title: picasso-强大的Android图片下载缓存库 [本文转载自:泡在网上的日子 参考:http://bl ...
- picasso-强大的Android图片下载缓存库
编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! pica ...
- android开源项目:图片下载缓存库picasso
picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能. picasso有如下特性: 在a ...
- Android 图片加载库Glide 实战(二),占位符,缓存,转换自签名高级实战
http://blog.csdn.net/sk719887916/article/details/40073747 请尊重原创 : skay <Android 图片加载库Glide 实战(一), ...
- 如何使用picasso 对Android图片下载缓存
相比较其他,picasso的图片缓存更加简单一些,他只需要一行代码就可以表述:导入相关jar包 Picasso.with(context).load("图片路径").into(Im ...
- fackbook的Fresco (FaceBook推出的Android图片加载库-Fresco)
[Android开发经验]FaceBook推出的Android图片加载库-Fresco 欢迎关注ndroid-tech-frontier开源项目,定期翻译国外Android优质的技术.开源库.软件 ...
- FaceBook推出的Android图片加载库-Fresco
FaceBook推出的Android图片加载库-Fresco 原文链接:Introducing Fresco: A new image library for Android 译者 : ZhaoKai ...
- Android图片加载库的理解
前言 这是“基础自测”系列的第三篇文章,以Android开发需要熟悉的20个技术点为切入点,本篇重点讲讲Android中的ImageLoader这个库的一些理解,在Android上最让人头疼是 ...
- android图片加载库Glide
什么是Glide? Glide是一个加载图片的库,作者是bumptech,它是在泰国举行的google 开发者论坛上google为我们介绍的,这个库被广泛的运用在google的开源项目中. Glide ...
随机推荐
- sb error
width: $("#StudentManagement").parent().width(), height: $("#StudentManagement") ...
- SVN提交时显示:Path is not a working copy directory
说明你地址没有checkout啊 先checkout,才能add和commi. 要是在一个已有的项目出现这个错误,就是包含这个地址的文件夹没添加进去,去上一层再试一次. 总之,养成在项目根目录提交的习 ...
- day0203 XML 学习笔记
day02, 03 1. xml语言和作用 2. xml语法详解 2.1 xml 语法声明 2.1.1 encoding 属性 2.1.2 standalone 属性 2.2 xml 元素(Eleme ...
- 聊聊LightProbe原理实现以及对LightProbe数据的修改
0x00 前言 最近工作比较忙,所以文章已经很久没有更新了.这篇小文的主题也是在出差的高铁上想到,因为最近和一些朋友聊天,发现他们中很多人的项目中都使用了多个实时光源.细问之下主要是某些物体,例如角色 ...
- Docker基本架构
Docker 采用了 C/S架构,包括客户端和服务端. Docker daemon 作为服务端接受来自客户的请求,并处理这些请求(创建.运行.分发容器). 客户端和服务端既可以运行在一个机器上,也可通 ...
- Bootstrap3 排版-缩略语
当鼠标悬停在缩写和缩写词上时就会显示完整内容,Bootstrap 实现了对 HTML 的 <abbr> 元素的增强样式.缩略语元素带有 title 属性,外观表现为带有较浅的虚线框,鼠标移 ...
- move_uploaded_file的failed to open stream错误处理
PHP的基本语法学习的差不多了,现在开始学习PHP的文件上传功能实现了.功能中使用到了move_uploaded_file方法,运行时报错: failed to open stream. 经过查资料, ...
- 20160218.CCPP体系详解(0028天)
程序片段(01):加法.c 内容概要:字符串计算表达式 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <st ...
- 20160213.CCPP体系详解(0023天)
程序片段(01):全排列.c 内容概要:全排列密码库 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <std ...
- Angular2入坑指南
序 对后端开发来说,前端是神秘的,眼花缭乱的技术,繁多的框架,出名的不出名的好几百种,看是"繁荣",其实显得杂乱无章,但是我们在做开发的时候,技术选型还是主流的那么几个:浅析ang ...