毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
2016-06-24 00:24
776 查看
毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选
官网: http://square.github.io/picasso/
我们在上篇OkHttp的时候说过这个Picasso,学名毕加索,是Square公司开源的一个Android图形缓存库,而且使用起来也是非常的简单,只要一行代码就轻松搞定了,你会问,为什么不介绍一下Glide?其实Glide我有时间也是会介绍的,刚好上篇我们用到了Picasso,所以就聊下这个,其实现在网上已经有很多关于Picasso的文章了,而Glide是Google的一位工程师根据Picasso做了很多优化的一个库,孰强孰弱,大家这块看看这个前辈的文章:
https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en
好的,我们就正式的开始今天的文章吧!
一.准备工作
图片缓存一直是个老掉牙的套路,即使众多老司机,也有不少在这里翻出,一言不合就大打出手的更加不计其数,我们在开发中要考虑很多种情况,比如
在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的话,可以去看我的博文
OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据
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 "; } }
做完实体类,我们有数据封装方式了,那就直接去写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还是比较简单的,如果不会,可以移步我的博文
[url=http://blog.csdn.net/qq_26787115/article/details/51366708]Android JSON原生解析的几种思路,以号码归属地,笑话大全,天气预报为例演示
Android JSON解析库Gson和Fast-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实现微信精选
- Python的网络编程库Gevent的安装及使用技巧
- ios扩展http服务,将iphone做小型的http服务器
- Visualizing MNIST 降维探索
- http-关于application/x-www-form-urlencoded等字符编码的解释说明
- android之网络操作(1)
- EntityFramework.SqlServer.dll 中发生 其他信息: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接)
- HTTP网页错误代码---网络、端口
- Python网络爬虫(1)
- Xml解析网络数据
- Http请求模拟报文返回工具HttpSimulation分享
- HttpServletRequest 和 HttpServletResponse对象
- 思科基础命令大全
- Android Https相关完全解析 当OkHttp遇到Https
- 神经网络Trick之DropConnect
- 子网划分举例
- 在MVC里使用 HttpContext.Response输出内容
- 网络编程socket(服务端简单模拟)(OC)
- 神经网络的Trick之Dropout的理解与实现
- Unable to download data from http://ruby.taobao.org/ & don't have write permissions for the /Library/Ruby/Gems/2.0.0 directory.