请求网络图片缓存到本地 ,还有一些现成的图片加载框架的使用 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应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取.再从文件中获取,最后才会访问网络. ...
随机推荐
- Sharepoint2013搜索学习笔记之设置外网内容源(四)
第一步,进入管理中心,点击管理应用程序,点击search service 应用程序进入到搜索管理配置页面,选择内容源 第二步,点击新建内容源,给内容源命名,在爬网内容类型中选网站,在爬网设置中选中仅对 ...
- sql server 简单语句整合
1.去重distinct , group by select distinct userid,username from 表名 select userid,username from 表名 group ...
- 搜索引擎Hoot的源码阅读(提供源码)
开门见山,最近阅读了一下一款开源引擎的源码,受益良多(学到了一些套路).外加好久没有写博客了(沉迷吃鸡,沉迷想念姑娘),特别开一篇.Hoot 的源码地址, 原理介绍地址.外加我看过之后的注释版本,当然 ...
- 获取服务端https证书 - Java版
接上篇,用java代码实现一下获取远程服务端证书,还是拿新浪首页测试,上代码: package org.test; import java.net.URL; import java.security. ...
- WinForm中TabControl的使用
TabControl和TabPage之间有一个默认颜色的边框,很难去除,需要重写TabControl控件重绘区域 public class FullTabControl : TabControl { ...
- 说一下我认识的*nix下的服务器热重启
步骤: 第一: 收到SIGTERM以后现在的服务器监听socket停止accept 但是并没有停止listen,这个很关键.(所以客户端发起的tcp连接的syn得不到synack,只是继续等待,而不会 ...
- 关于nosql的讲解
Data Base 关于nosql的讲解 nosql非关系型数据库. 优点: 1.可扩展 2.大数据量,高性能 3.灵活的数据模型 4.高可用 缺点: 1.不正式 2.不标准 非关系型数据库有哪些: ...
- 如何从Spring官网下载Spring的jar包
Spring官网:https://spring.io/ 进入官网点击PRODECTS 然后点击Spring Framework 进入下面的页面点击小猫图标: 之后再下面的页面持续向下滚动,找到下图我标 ...
- networkX如何读取存储图的二进制.dat文件
一般情况下,.dat文件存储的是图的二进制邻接矩阵. import networkx as nx G = nx.readadjlist('auth_graph.dat')
- 【BZOJ 2679】[Usaco2012 Open]Balanced Cow Subsets(折半搜索+双指针)
[Usaco2012 Open]Balanced Cow Subsets 题目描述 给出\(N(1≤N≤20)\)个数\(M(i) (1 <= M(i) <= 100,000,000)\) ...