请求网络图片缓存到本地 ,还有一些现成的图片加载框架的使用 Ace网络篇(一)
现在去买年货~~~~~~ 占坑,
现在来填坑 填完睡觉,感谢这俩月的把自己往死里逼得奋斗从JAVA什么都不懂到现在,做这些也是给在自学路上的新人(我也是菜鸟)一点点我力所能及的帮助,等我水平更高了还会继续分享,分享,开源是种快乐.
这篇讲你怎样获取一张网络图片,很基础,但我还是那句话 万变不理其中,很多集成好的框架也是这个原理,框架虽易但希望你能懂得其中原理,代码再复杂,也是这种"一招一式"
现在来看请求一张照片分几步走:
获取网络图片
这里我并没有说异步线程,我直接在主线程执行这些
1 确定图片的网址
2 发送http请求
URL url = new URL(address);
//获取连接对象,并没有建立连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置连接和读取超时
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
//设置请求方法,注意必须大写
conn.setRequestMethod("GET");
//建立连接,发送get请求
//conn.connect();
//建立连接,然后获取响应吗,200说明请求成功
conn.getResponseCode();
* 服务器的图片是以流的形式返回给浏览器的 //拿到服务器返回的输入流
InputStream is = conn.getInputStream();
//把流里的数据读取出来,并构造成图片
Bitmap bm = BitmapFactory.decodeStream(is);
* 把图片设置为ImageView的显示内容 ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setImageBitmap(bm);
3 别忘了添加权限
代码:布局就一个imageview和button 不写了 记得添加网络请求权限
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View v){
String path = "http://pic.cnblogs.com/avatar/859887/20160120170921.png";
//我酷炫吊炸天可爱卖萌的羊驼
//发送http请求
try {
//1.使用网址构造一个URL对象
URL url = new URL(path);
//2.获取连接对象
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//3.设置一些属性
//设置请求方式,注意大写
conn.setRequestMethod("GET");
//设置请求超时
conn.setConnectTimeout(8000);
//设置读取超时
conn.setReadTimeout(8000);
//4.发送请求,建立连接
conn.connect();
//5.判断请求是否成功
if(conn.getResponseCode() == 200){
//获取服务器返回的流,流里就是客户端请求的数据
InputStream is = conn.getInputStream();
//读取流里的数据,构造出一张图片
Bitmap bm = BitmapFactory.decodeStream(is);
//把下载的图片显示至imageview
ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setImageBitmap(bm);
}
else{
Toast.makeText(this, "请求失败了亲~~", 0).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
其实我不开子线程是个坑下面给我自己写个坑:
来 让主线程sleep 10秒......系统会抛出Application Not Response
因为主线程不能被阻塞:
1 在Android中,主线程被阻塞会导致应用不能刷新ui界面,不能响应用户操作,用户体验将非常差
2 主线程阻塞时间过长,系统会抛出ANR异常
3 ANR:Application Not Response;应用无响应
4 任何耗时操作都不可以写在主线程
5 因为网络交互属于耗时操作,如果网速很慢,代码会阻塞,所以网络交互的代码不能运行在主线程
那么我们需要开启子线程,开启子线程的两种方法:请看我的这个教程会再讲三个知识点:消息队列,主线程(UI线程),缓存到本地文件
一 只有主线程能刷新ui:
1 刷新ui的代码只能运行在主线程,运行在子线程是没有任何效果的
2 如果需要在子线程中刷新ui,使用消息队列机制
3 主线程也叫ui线程
二 消息队列
1 主线程创建时,系统会同时创建消息队列对象(MessageQueue)和消息轮询器对象(Looper)
2 轮询器的作用,就是不停的检测消息队列中是否有消息(Message)
3 Looper一旦发现Message Queue中有消息,就会把消息取出,然后把消息扔给Handler对象,Handler会调用自己的handleMessage方法来处理这条消息
4 handleMessage方法运行在主线程
5 主线程创建时,消息队列和轮询器对象就会被创建,但是消息处理器对象,需要使用时,自行创建
主线程创建:
//消息队列
Handler handler = new Handler(){
//主线程中有一个消息轮询器looper,不断检测消息队列中是否有新消息,如果发现有新消息,自动调用此方法,注意此方法是在主线程中运行的
public void handleMessage(android.os.Message msg) { }
};
在子线程中使用Handler对象往消息队列里发消息
//创建消息对象
Message msg = new Message();
//消息的obj属性可以赋值任何对象,通过这个属性可以携带数据
msg.obj = bm;
//what属性相当于一个标签,用于区分出不同的消息,从而运行不能的代码
msg.what = 1;
//发送消息
handler.sendMessage(msg);
通过switch语句区分不同的消息
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
//如果是1,说明属于请求成功的消息
case 1:
ImageView iv = (ImageView) findViewById(R.id.iv);
Bitmap bm = (Bitmap) msg.obj;
iv.setImageBitmap(bm);
break;
case 2:
Toast.makeText(MainActivity.this, "请求失败", 0).show();
break;
}
}
缓存图片到本地的功能:
把服务器返回的流里的数据读取出来,然后通过文件输入流写至本地文件
//1.拿到服务器返回的输入流
InputStream is = conn.getInputStream();
//2.把流里的数据读取出来,并构造成图片 FileOutputStream fos = new FileOutputStream(file);
byte[] b = new byte[1024];
int len = 0;
while((len = is.read(b)) != -1){
fos.write(b, 0, len);
}
创建bitmap对象的代码改成
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
每次发送请求前检测一下在缓存中是否存在同名图片,如果存在,则读取缓存
看代码吧
public class MainActivity extends Activity {
Handler handler = new Handler(){
//只要消息队列有消息,此方法就会在主线程执行
public void handleMessage(android.os.Message msg) {
//在这里刷新ui
switch (msg.what) {
case 1:
ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setImageBitmap((Bitmap)msg.obj);
break;
case 2:
Toast.makeText(MainActivity.this, "请求失败o(╯□╰)o", 0).show();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View v){
final String path = "http://pic.cnblogs.com/avatar/859887/20160120170921.png";
final File file = new File(getCacheDir(), getNameFromPath(path));
if(file.exists()){
System.out.println("从缓存获取");
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
Message msg = new Message();
msg.obj = bm;
msg.what = 1;
handler.sendMessage(msg);
// ImageView iv = (ImageView) findViewById(R.id.iv);
// iv.setImageBitmap((Bitmap)msg.obj);
}
else{
Thread t = new Thread(){
@Override
public void run() {
System.out.println("从网络获取");
//发送http请求
try {
//1.使用网址构造一个URL对象
URL url = new URL(path);
//2.获取连接对象
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//3.设置一些属性
//设置请求方式,注意大写
conn.setRequestMethod("GET");
//设置请求超时
conn.setConnectTimeout(8000);
//设置读取超时
conn.setReadTimeout(8000);
//4.发送请求,建立连接
// conn.connect();
//5.判断请求是否成功
if(conn.getResponseCode() == 200){
//获取服务器返回的流,流里就是客户端请求的数据
InputStream is = conn.getInputStream();
//我们自己读取流里的数据,读取1k,就把1k写到本地文件缓存起来
byte[] b = new byte[1024];
int len;
FileOutputStream fos = new FileOutputStream(file);
while((len = is.read(b)) != -1){
fos.write(b, 0, len);
}
fos.close();
// 因为缓存时已经把流里数据读取完了,此时流里没有任何数据
// Bitmap bm = BitmapFactory.decodeStream(is);
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
//当子线程需要刷新ui时,只需发送一条消息至消息队列
Message msg = new Message();
//消息对象本身是可以携带数据的
msg.obj = bm;
//使用what标注消息是什么类型的
msg.what = 1;
handler.sendMessage(msg);
}
else{
//如果消息池有消息,取出消息池第一条消息,返回,如果没有,就new一个消息返回
// Message msg = handler.obtainMessage();
// msg.what = 2;
// handler.sendMessage(msg);
handler.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
}
}
public String getNameFromPath(String path){
int index = path.lastIndexOf("/");
return path.substring(index + 1);
}
}
更多开启线程加载图片的教程可以看我的这个教程
阿冰教你一步一步做Android新闻客户端(二)两种异步线程加载图片的方法
眼皮子打架了 我要睡了 明天讲框架 框架就太简单了 教会你用框架只要一秒 但是不懂原理你永远不会进步.
爬起来补坑 下面你自己动手:
1 github.com
2 在github搜索smart-image-view
3 下载开源项目smart-image-view
4 使用自定义组件时,标签名字要写包名(再XML文件里替换刚才我们创建的ImageView)<com.loopj.android.image.SmartImageView/>
SmartImageView的使用
SmartImageView siv = (SmartImageView) findViewById(R.id.siv);
siv.setImageUrl("http://pic.cnblogs.com/avatar/859887/20160120170921.png");//还是我们可爱的羊驼
请求网络图片缓存到本地 ,还有一些现成的图片加载框架的使用 Ace网络篇(一)的更多相关文章
- android-------非常好的图片加载框架和缓存库(Picasso)
Picasso是Square公司开源的一个Android图形缓存库, 可以实现图片加载(本地和网络)和缓存功能. 地址:http://square.github.io/picasso/ jar包下载: ...
- Android图片加载框架最全解析(三),深入探究Glide的缓存机制
在本系列的上一篇文章中,我带着大家一起阅读了一遍Glide的源码,初步了解了这个强大的图片加载框架的基本执行流程. 不过,上一篇文章只能说是比较粗略地阅读了Glide整个执行流程方面的源码,搞明白了G ...
- android--------Universal-Image-Loader图片加载框架和结合LruCache缓存图片
本博客包含包含Android-Universal-Image-Loader 网络图片加载框架实现图片加载和结合universal-image-loader与LruCache来自定义缓存图片,可以设置缓 ...
- Android图片加载与缓存开源框架:Android Glide
<Android图片加载与缓存开源框架:Android Glide> Android Glide是一个开源的图片加载和缓存处理的第三方框架.和Android的Picasso库类似,个人感觉 ...
- Volley框架之网络请求和图片加载
Volley是 Google 推出的 Android 异步网络请求框架和图片加载框架. Volley的特性 (1).封装了的异步的请求API.Volley 中大多是基于接口的设计,可配置性强.(2). ...
- Android 图片加载库Glide 实战(二),占位符,缓存,转换自签名高级实战
http://blog.csdn.net/sk719887916/article/details/40073747 请尊重原创 : skay <Android 图片加载库Glide 实战(一), ...
- android--------volley之网络请求和图片加载
Volley是 Google 推出的 Android 异步网络请求框架和图片加载框架. Volley的特性 封装了的异步的请求API.Volley 中大多是基于接口的设计,可配置性强. 一个优雅和稳健 ...
- Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片
一.问题描述 为提高图片加载的效率,需要对图片的采用缓存和异步加载策略,编码相对比较复杂,实际上有一些优秀的框架提供了解决方案,比如近期在git上比较活跃的xutil框架 Xutil框架提供了四大模块 ...
- Android批量图片加载经典系列——采用二级缓存、异步加载网络图片
一.问题描述 Android应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取.再从文件中获取,最后才会访问网络. ...
随机推荐
- CSS概念 - 可视化格式模型(二) 定位概述(普通流、绝对定位)
2.定位概念 上一节熟悉了盒模型, 现在来看一下可视化格式模型和定位模型. 理解这两个模型的细微差异是非常重要的, 因为它们一起控制着如何在页面上布置每个元素 2.1 可视化格式模型 CSS有三种基本 ...
- .net 序列化 与反序列化 Serializable
序列化:序列化指的是 将对象 通过流的方式 保存为一个文件. 反序列化则是将该文件还原成 对象的过程. 序列化的作用:序列化可以跨语言跨平台 传输数据,将某一对象序列化成通用的文件格式在进行传输. 比 ...
- mac 地址查询
mac 地址由 6个字节(48bit)组成.前3个字节是厂商代码.输入厂商名称可查询相应的代码. http://standards.ieee.org/develop/regauth/oui/publi ...
- linux 建议锁和强制锁
作为APUE 14.3节的参考 linux是有强制锁的,但是默认不开启.想让linux支持强制性锁,不但在mount的时候需要加上-o mand,而且对要加锁的文件也需要设置相关权限. . ...
- 十一、Node.js监听代码改动自动重启node插件supervisor
我们慢慢地发现,每次我们稍微改变js代码都需要重启服务才能在浏览器显示新的效果,很麻烦,这里我们可以通过npm命令安装supervisoror插件,安装方法如下 之前章节我们知道安装了nodejs就会 ...
- ubuntu没有权限(不能)创建文件夹(目录)
可以在终端直接运行 sudo nautilus,弹出来的nautilus可以直接GUI操作,中途别关终端.如果遇到需要输入root密码,则输入root密码就可以启动这个图形界面了.
- 20165219 2017-2018-2 《Java程序设计》第4周学习总结
20165219 2017-2018-2 <Java程序设计>第4周学习总结 课本知识总结 第五章 在java中,继承时使用extends关键字,private成员也会被继承,只不过子类无 ...
- iOS 开发之 GCD 不同场景使用
header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...
- 2018数学建模A题优秀论文:高温作业专用服装设计
高温作业专用服装设计 摘 要 本文针对多层材料的高温作业服装的传热问题进行研究,综合考虑多种传热方式建立传热模型,并以此模型为基础解决了服装设计中各层材料最佳厚度的问题. 对于问题一,要求在热物性系数 ...
- oracle知识总结
Oracle 分页案例: SELECT * FROM(SELECT A.*, ROWNUM RN FROM (SELECT * FROM Table_name) AWHERE ROWNUM <= ...