请求网络图片缓存到本地 ,还有一些现成的图片加载框架的使用 Ace网络篇(一)
2016-01-31 14:15
701 查看
现在去买年货~~~~~~ 占坑,
现在来填坑 填完睡觉,感谢这俩月的把自己往死里逼得奋斗从JAVA什么都不懂到现在,做这些也是给在自学路上的新人(我也是菜鸟)一点点我力所能及的帮助,等我水平更高了还会继续分享,分享,开源是种快乐.
这篇讲你怎样获取一张网络图片,很基础,但我还是那句话 万变不理其中,很多集成好的框架也是这个原理,框架虽易但希望你能懂得其中原理,代码再复杂,也是这种"一招一式"
现在来看请求一张照片分几步走:
获取网络图片
这里我并没有说异步线程,我直接在主线程执行这些
1 确定图片的网址
2 发送http请求
3 别忘了添加权限
代码:布局就一个imageview和button 不写了 记得添加网络请求权限
其实我不开子线程是个坑下面给我自己写个坑:
来 让主线程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对象往消息队列里发消息
缓存图片到本地的功能:
把服务器返回的流里的数据读取出来,然后通过文件输入流写至本地文件
创建bitmap对象的代码改成
Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath());
每次发送请求前检测一下在缓存中是否存在同名图片,如果存在,则读取缓存
看代码吧
爬起来补坑 下面你自己动手:
1 github.com
2 在github搜索smart-image-view
3 下载开源项目smart-image-view
4 使用自定义组件时,标签名字要写包名(再XML文件里替换刚才我们创建的ImageView)<com.loopj.android.image.SmartImageView/>
SmartImageView的使用
现在来填坑 填完睡觉,感谢这俩月的把自己往死里逼得奋斗从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");//还是我们可爱的羊驼
相关文章推荐
- 机器学习-神经元网络
- 网络流建图的几点体会(给自己看的笔记,持续更新)
- HttpUrlConnection实现文件下载
- 网络——Base64Encode(转:自定义Base64编码器——Base64Encode)
- android 项目中使用到的网络请求框架以及怎样配置好接口URL
- 网络——获取Web数
- iOS开发-- 常见坑(网络下载失败)
- HTTP 协议漫谈
- PHP获得真实客户端的真实IP REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR
- OKHttp3.0的日常及入门
- 禁用APP Transport Security以访问http链接
- Android 网络通信API的选择和实现实例
- 交叉编译tcpdump
- http原理
- Hadoop—distcp
- 【转】TCP层的分段和IP层的分片之间的关系 MTU和MSS存在的关系
- HTTP 响应
- 设置笔记本与台式电脑网络共享
- Linux IPv6网络编程之UDP实例
- 网络工具类