android异步加载图片显示,并且对图片进行缓存实例
来源:互联网 发布:最近网络上很火的歌曲 编辑:程序博客网 时间:2024/05/01 04:35
android异步加载图片显示,并且对图片进行缓存实例
分类: Android2013-04-16 14:31 493人阅读 评论(4) 收藏 举报
step1:新建项目DataAsyncLoad,如下图所示
step2:设置应用的UI界面
a.应用的主界面 main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <ListView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:id="@+id/listView"
- />
- </LinearLayout>
b.每个ListView的界面 listview_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal" >
- <ImageView
- android:layout_width="42dp"
- android:layout_height="42dp"
- android:id="@+id/imageView"
- />
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:textColor="#FFFFFF"
- android:id="@+id/textView"
- />
- </LinearLayout>
step3:写一些辅助类 cn.roco.data.utilsMD5.java
- package cn.roco.data.utils;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- public class MD5 {
- public static String getMD5(String content) {
- try {
- MessageDigest digest = MessageDigest.getInstance("MD5");
- digest.update(content.getBytes());
- return getHashString(digest);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return null;
- }
- private static String getHashString(MessageDigest digest) {
- StringBuilder builder = new StringBuilder();
- for (byte b : digest.digest()) {
- builder.append(Integer.toHexString((b >> 4) & 0xf));
- builder.append(Integer.toHexString(b & 0xf));
- }
- return builder.toString();
- }
- }
- package cn.roco.data.domain;
- public class Contact {
- private int id;
- private String name;
- private String image;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getImage() {
- return image;
- }
- public void setImage(String image) {
- this.image = image;
- }
- public Contact(int id, String name, String image) {
- this.id = id;
- this.name = name;
- this.image = image;
- }
- public Contact(){
- }
- }
step5:写一个应用的service层,用于对javabean进行操作 cn.roco.data.service.ContactService.java
- package cn.roco.data.service;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.List;
- import org.xmlpull.v1.XmlPullParser;
- import android.net.Uri;
- import android.util.Xml;
- import cn.roco.data.domain.Contact;
- import cn.roco.data.utils.MD5;
- public class ContactService {
- /**
- * 获取联系人数据
- *
- * @return
- * @throws Exception
- */
- public static List<Contact> getContacts() throws Exception {
- String path = "http://192.168.1.100:8080/Hello/contact.xml";
- HttpURLConnection connection = (HttpURLConnection) new URL(path)
- .openConnection();
- connection.setConnectTimeout(5000);
- connection.setRequestMethod("GET");
- if (connection.getResponseCode() == 200) {
- return parseXML(connection.getInputStream());
- }
- return null;
- }
- /**转化XML获取数据
- * 服务器端的xml文件如下。。。。。。
- * <?xml version="1.0" encoding="UTF-8"?>
- <contacts>
- <contact id="1">
- <name>Roco_1</name>
- <image src="http://192.168.1.100:8080/Hello/images/1.png" />
- </contact>
- .......
- </contacts>*/
- private static List<Contact> parseXML(InputStream inputStream)
- throws Exception {
- List<Contact> contacts = new ArrayList<Contact>();
- Contact contact = null;
- XmlPullParser pullParser = Xml.newPullParser();
- pullParser.setInput(inputStream, "UTF-8");
- int event = pullParser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- switch (event) {
- case XmlPullParser.START_TAG:
- if ("contact".equals(pullParser.getName())) {
- contact = new Contact();
- contact.setId(new Integer(pullParser.getAttributeValue(0)));
- } else if ("name".equals(pullParser.getName())) {
- contact.setName(pullParser.nextText());
- } else if ("image".equals(pullParser.getName())) {
- contact.setImage(pullParser.getAttributeValue(0));
- }
- break;
- case XmlPullParser.END_TAG:
- if ("contact".equals(pullParser.getName())) {
- contacts.add(contact);
- contact = null;
- }
- }
- event = pullParser.next();
- }
- return contacts;
- }
- /**
- * 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
- *
- * @param path
- * 图片路径
- * @return
- */
- public static Uri getImage(String imagePath, File cacheDir)
- throws Exception {
- //缓存文件的文件名用MD5进行加密
- File localFile = new File(cacheDir, MD5.getMD5(imagePath)
- + imagePath.substring(imagePath.lastIndexOf(".")));
- if (localFile.exists()) {
- return Uri.fromFile(localFile);
- } else {
- HttpURLConnection connection = (HttpURLConnection) new URL(
- imagePath).openConnection();
- connection.setConnectTimeout(5000);
- connection.setRequestMethod("GET");
- //将文件缓存起来
- if (connection.getResponseCode() == 200) {
- FileOutputStream outputStream = new FileOutputStream(localFile);
- InputStream inputStream = connection.getInputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while ((len = inputStream.read(buffer)) != -1) {
- outputStream.write(buffer, 0, len);
- }
- inputStream.close();
- outputStream.close();
- return Uri.fromFile(localFile);
- }
- }
- return null;
- }
- }
step6:写一个Adapter用于对ListView进行数据更新 cn.roco.data.adapter.ContactAdapter.java
- package cn.roco.data.adapter;
- import java.io.File;
- import java.util.List;
- import cn.roco.data.R;
- import cn.roco.data.domain.Contact;
- import cn.roco.data.service.ContactService;
- import android.content.Context;
- import android.net.Uri;
- import android.os.AsyncTask;
- import android.os.Handler;
- import android.os.Message;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.TextView;
- /**适配器,用于更新View*/
- public class ContactAdapter extends BaseAdapter {
- private List<Contact> data;
- private int listviewItem;
- private File cache;
- /**
- * LayoutInflater的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout文件夹下的xml布局文件,并且实例化!
- * 而 findViewById()是找具体某一个xml下的具体 widget控件(如:Button,TextView等)。
- */
- private LayoutInflater layoutInflater;
- public ContactAdapter(Context context, List<Contact> data,
- int listviewItem, File cache) {
- this.data = data;
- this.listviewItem = listviewItem;
- this.cache = cache;
- this.layoutInflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);//取得xml里定义的view
- /***
- * getSystemService()是Android很重要的一个API,它是Activity的一个方法,
- * 根据传入的NAME来取得对应的Object,然后转换成相应的服务对象。以下介绍系统相应的服务。
- * 传入的Name 返回的对象 说明
- WINDOW_SERVICE WindowManager 管理打开的窗口程序
- LAYOUT_INFLATER_SERVICE LayoutInflater 取得xml里定义的view
- ACTIVITY_SERVICE ActivityManager 管理应用程序的系统状态
- POWER_SERVICE PowerManger 电源的服务
- ALARM_SERVICE AlarmManager 闹钟的服务
- NOTIFICATION_SERVICE NotificationManager 状态栏的服务
- KEYGUARD_SERVICE KeyguardManager 键盘锁的服务
- LOCATION_SERVICE LocationManager 位置的服务,如GPS
- SEARCH_SERVICE SearchManager 搜索的服务
- VEBRATOR_SERVICE Vebrator 手机震动的服务
- CONNECTIVITY_SERVICE Connectivity 网络连接的服务
- WIFI_SERVICE WifiManager Wi-Fi服务
- TELEPHONY_SERVICE TeleponyManager 电话服务
- */
- }
- /** 得到数据的总数 */
- @Override
- public int getCount() {
- return data.size();
- }
- /** 根据数据索引,得到集合中所对应的数据 */
- @Override
- public Object getItem(int position) {
- return data.get(position);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ImageView imageView = null;
- TextView textView = null;
- if (convertView == null) {
- convertView = layoutInflater.inflate(listviewItem, null);
- imageView = (ImageView) convertView.findViewById(R.id.imageView);
- textView = (TextView) convertView.findViewById(R.id.textView);
- convertView.setTag(new DataWrapper(imageView, textView));//将内容包装起来以备以后使用
- } else {
- DataWrapper dataWrapper=(DataWrapper) convertView.getTag();//将包装类取出来
- //从包装类中取数据
- imageView=dataWrapper.getImageView();
- textView=dataWrapper.getTextView();
- }
- Contact contact=data.get(position);
- textView.setText(contact.getName());
- /**异步加载图片文件*/
- asynchImageLoad(imageView,contact.getImage());
- return convertView;
- }
- /*
- //该方法会创建很多的线程,也会很耗资源
- private void asynchImageLoad(final ImageView imageView, final String imagePath) {
- final Handler handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {//运行在主线程中
- Uri uri=(Uri) msg.obj;
- if (uri!=null&&imageView!=null) {
- imageView.setImageURI(uri);
- }
- }
- };
- Runnable runnable=new Runnable() {
- @Override
- public void run() {
- try {
- Uri uri=ContactService.getImage(imagePath, cache);
- handler.sendMessage(handler.obtainMessage(10,uri));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- new Thread(runnable).start();
- }
- */
- /**异步加载图片文件*/
- private void asynchImageLoad(ImageView imageView, String imagePath) {
- AsycImageTask asycImageTask=new AsycImageTask(imageView);
- asycImageTask.execute(imagePath);
- }
- /**
- * 使用AsyncTask提高性能
- * 可选方法:
- 1, onprogressupdate(progress…) 可以使用进度条增加用户体验度。此方法在主线程执行,用户显示任务执行的进度。
- 2, onpreExecute() 这里是最新用户调用excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
- 3, onCancelled() 用户调用取消时,要做的操作。
- AsyncTask<Params, Progress, Result>
- AsyscTask定义了三种泛型类型params,progress和result.
- 1, params启动任务执行的输入参数,比如http请求的URL
- 2, progress后台任务执行的百分比
- 3, result后台执行任务最终返回的结果,比如String,比如我需要得到的list。
- 使用AsyncTask类,遵守的准则:1, Task的实例必须在UI thread中创建;2, Execute方法必须在UI thread中调用
- 3, 不要手动的调用onPfreexecute(),onPostExecute(result)Doinbackground(params…),onProgressupdate(progress…)这几个方法;
- 4, 该task只能被执行一次,否则多次调用时将会出现异常;
- AsyncTask的整个调用过程都是从execute方法开始的,一旦在主线程中调用execute方法,就可以通过onpreExecute方法,
- 这是一个预处理方法,比如可以在这里开始一个进度框,同样也可以通过onprogressupdate方法给用户一个进度条的显示,增加用户体验;
- 最后通过onpostexecute方法,相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果处理操作UI。
- 此方法在主线程执行,任务执行的结果作为此方法的参数返回
- */
- private final class AsycImageTask extends AsyncTask<String, Integer, Uri>{
- private ImageView imageView;
- public AsycImageTask(ImageView imageView) {
- this.imageView=imageView;
- }
- /**
- * 后台执行,比较耗时的操作都可以放在这里。
- 注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作
- ,通常需要较长的时间。在执行过程中可以调用
- Public progress(progress…)来更新任务的进度。
- */
- @Override
- protected Uri doInBackground(String... params) {//子线程中执行
- try {
- return ContactService.getImage(params[0], cache);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * 相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果
- * 处理操作UI。此方法在主线程执行,任务执行的结果作为此方法的参数返回。
- */
- @Override
- protected void onPostExecute(Uri result) {//运行在主线程
- if (result!=null&&imageView!=null) {
- imageView.setImageURI(result);
- }
- }
- }
- /**数据包装类*/
- private final class DataWrapper {
- private ImageView imageView;
- private TextView textView;
- public ImageView getImageView() {
- return imageView;
- }
- public TextView getTextView() {
- return textView;
- }
- public DataWrapper(ImageView imageView, TextView textView) {
- this.imageView = imageView;
- this.textView = textView;
- }
- }
- }
step7:应用的主程序 cn.roco.data.MainActivity.java
- package cn.roco.data;
- import java.io.File;
- import java.util.List;
- import cn.roco.data.adapter.ContactAdapter;
- import cn.roco.data.domain.Contact;
- import cn.roco.data.service.ContactService;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.widget.ListView;
- public class MainActivity extends Activity {
- private ListView listView;
- /**缓存文件*/
- private File cache;
- /**接受消息,处理消息 ,此Handler会与当前主线程一块运行
- * 使用匿名内部类来复写Handler当中的handlerMessage()方法 */
- Handler handler = new Handler() {
- // 接受数据
- public void handleMessage(android.os.Message msg) {
- //设置适配器,将获取的数据使用适配器更新View
- listView.setAdapter(new ContactAdapter(MainActivity.this,
- (List<Contact>) msg.obj, R.layout.listview_item, cache));
- };
- };
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- listView = (ListView) this.findViewById(R.id.listView);
- /**在SD卡中生成缓存目录*/
- cache = new File(Environment.getExternalStorageDirectory(), "cache");
- /**如果目录不存在就新建一个*/
- if (!cache.exists()) cache.mkdir();
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- //获取联系人数据
- List<Contact> data= ContactService.getContacts();
- // 向Handler发送消息,更新UI
- handler.sendMessage(handler.obtainMessage(22, data));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- @Override
- protected void onDestroy() {
- /**清除缓存文件*/
- for (File file:cache.listFiles()) {
- file.delete();
- }
- cache.delete();
- super.onDestroy();
- }
- }
step8:AndroidManifest.xml
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cn.roco.data" android:versionCode="1" android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
- <!-- 访问Internet权限 -->
- <uses-permission android:name="android.permission.INTERNET" />
- <!-- 在SD卡中创建和删除文件权限 -->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
- <!-- 往SD卡中写入数据权限 -->
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".MainActivity" android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
step9:编写服务器端的代码,主要是一个contact.xml文件
- <?xml version="1.0" encoding="UTF-8"?>
- <contacts>
- <contact id="1">
- <name>Roco_1</name>
- <image src="http://192.168.1.100:8080/Hello/images/1.png" />
- </contact>
- <contact id="2">
- <name>Roco_2</name>
- <image src="http://192.168.1.100:8080/Hello/images/2.png" />
- </contact>
- <contact id="3">
- <name>Roco_3</name>
- <image src="http://192.168.1.100:8080/Hello/images/3.png" />
- </contact>
- <contact id="4">
- <name>Roco_4</name>
- <image src="http://192.168.1.100:8080/Hello/images/4.png" />
- </contact>
- <contact id="5">
- <name>Roco_5</name>
- <image src="http://192.168.1.100:8080/Hello/images/5.png" />
- </contact>
- <contact id="6">
- <name>Roco_6</name>
- <image src="http://192.168.1.100:8080/Hello/images/6.png" />
- </contact>
- <contact id="7">
- <name>Roco_7</name>
- <image src="http://192.168.1.100:8080/Hello/images/7.png" />
- </contact>
- <contact id="8">
- <name>Roco_8</name>
- <image src="http://192.168.1.100:8080/Hello/images/8.png" />
- </contact>
- <contact id="9">
- <name>Roco_9</name>
- <image src="http://192.168.1.100:8080/Hello/images/9.png" />
- </contact>
- <contact id="10">
- <name>Roco_10</name>
- <image src="http://192.168.1.100:8080/Hello/images/10.png" />
- </contact>
- <contact id="11">
- <name>Roco_11</name>
- <image src="http://192.168.1.100:8080/Hello/images/11.png" />
- </contact>
- <contact id="12">
- <name>Roco_12</name>
- <image src="http://192.168.1.100:8080/Hello/images/12.png" />
- </contact>
- <contact id="13">
- <name>Roco_13</name>
- <image src="http://192.168.1.100:8080/Hello/images/13.png" />
- </contact>
- <contact id="14">
- <name>Roco_14</name>
- <image src="http://192.168.1.100:8080/Hello/images/14.png" />
- </contact>
- <contact id="15">
- <name>Roco_15</name>
- <image src="http://192.168.1.100:8080/Hello/images/15.png" />
- </contact>
- <contact id="16">
- <name>Roco_16</name>
- <image src="http://192.168.1.100:8080/Hello/images/16.png" />
- </contact>
- <contact id="17">
- <name>Roco_17</name>
- <image src="http://192.168.1.100:8080/Hello/images/17.png" />
- </contact>
- <contact id="18">
- <name>Roco_18</name>
- <image src="http://192.168.1.100:8080/Hello/images/18.png" />
- </contact>
- <contact id="19">
- <name>Roco_19</name>
- <image src="http://192.168.1.100:8080/Hello/images/19.png" />
- </contact>
- <contact id="20">
- <name>Roco_20</name>
- <image src="http://192.168.1.100:8080/Hello/images/20.png" />
- </contact>
- </contacts>
以及在images目录下放置了一些图片
step10:将项目部署到模拟器上运行效果如下图:
在SD卡中会生成缓存文件
当应用退出的时候,会将缓存文件删除
有了缓存文件,只要应用没有退出,即使联网不成功,也可以读取缓存中的图片文件
- android异步加载图片显示,并且对图片进行缓存实例
- android异步加载图片显示,并且对图片进行缓存实例
- 我的Android进阶之旅------>android异步加载图片显示,并且对图片进行缓存实例
- Android之ListView异步加载网络图片(优化缓存机制)和对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android 网络加载图片,对图片资源进行优化,并且实现内存双缓存 + 磁盘缓存
- android开发----异步下载图片,并且进行缓存和显示图片
- android异步图片加载中的图片缓存
- [Android]异步加载图片,内存缓存,文件缓存,imageview显示图片时增加淡入淡出动画
- Android异步下载图片并且缓存图片到本地
- Android异步下载图片并且缓存图片到本地
- 记录-- Android异步下载图片并且缓存图片到本地
- Android异步下载图片并且缓存图片到本地
- Android异步下载图片并且缓存图片到本地
- php在apache中安装模式的区别:fastcgi和mod_php
- 如何利用oracle第三方工具做数据库的性能优化 .
- 交流转直流电路
- Window_Open详解
- 防止内存泄露 Linux下用Valgrind做检查
- android异步加载图片显示,并且对图片进行缓存实例
- Mysql导入xx.sql文件的方法
- 热备份与冷备份区别 (转自CSDN下载)
- ssh 公钥方式认证攻略(原理)
- FlexPaper+SWFTools 实现仿百度文库及一些小问题
- android编写规范
- Android:使用ImageView和ScaleAnimation实现连续变化的ProgressBar效果
- oracle被锁住后的处理方式,错误Code:ora-00054
- 进程掩码及信号屏蔽(来自百度百科)