android异步加载图片显示,并且对图片进行缓存实例

来源:互联网 发布:最近网络上很火的歌曲 编辑:程序博客网 时间:2024/05/01 04:35

android异步加载图片显示,并且对图片进行缓存实例

分类: Android 493人阅读 评论(4) 收藏 举报

step1:新建项目DataAsyncLoad,如下图所示


step2:设置应用的UI界面

a.应用的主界面    main.xml

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <ListView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="fill_parent"   
  10.     android:id="@+id/listView"  
  11.     />  
  12. </LinearLayout>  

b.每个ListView的界面  listview_item.xml

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="horizontal" >  
  6.     <ImageView   
  7.         android:layout_width="42dp"  
  8.         android:layout_height="42dp"  
  9.         android:id="@+id/imageView"    
  10.         />  
  11.   
  12.     <TextView   
  13.         android:layout_width="match_parent"  
  14.         android:layout_height="wrap_content"  
  15.         android:textSize="18sp"  
  16.         android:textColor="#FFFFFF"  
  17.         android:id="@+id/textView"          
  18.         />  
  19. </LinearLayout>  

step3:写一些辅助类     cn.roco.data.utilsMD5.java

[java] view plaincopy
  1. package cn.roco.data.utils;  
  2. import java.security.MessageDigest;  
  3. import java.security.NoSuchAlgorithmException;  
  4.   
  5. public class MD5 {  
  6.     public static String getMD5(String content) {  
  7.         try {  
  8.             MessageDigest digest = MessageDigest.getInstance("MD5");  
  9.             digest.update(content.getBytes());  
  10.             return getHashString(digest);  
  11.               
  12.         } catch (NoSuchAlgorithmException e) {  
  13.             e.printStackTrace();  
  14.         }  
  15.         return null;  
  16.     }  
  17.       
  18.     private static String getHashString(MessageDigest digest) {  
  19.         StringBuilder builder = new StringBuilder();  
  20.         for (byte b : digest.digest()) {  
  21.             builder.append(Integer.toHexString((b >> 4) & 0xf));  
  22.             builder.append(Integer.toHexString(b & 0xf));  
  23.         }  
  24.         return builder.toString();  
  25.     }  
  26. }  


step4:写应用使用的JavaBean  cn.roco.data.domain.Contact.java

[java] view plaincopy
  1. package cn.roco.data.domain;  
  2.   
  3. public class Contact {  
  4.     private int id;  
  5.     private String name;  
  6.     private String image;  
  7.   
  8.     public int getId() {  
  9.         return id;  
  10.     }  
  11.   
  12.     public void setId(int id) {  
  13.         this.id = id;  
  14.     }  
  15.   
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.   
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.   
  24.     public String getImage() {  
  25.         return image;  
  26.     }  
  27.   
  28.     public void setImage(String image) {  
  29.         this.image = image;  
  30.     }  
  31.   
  32.     public Contact(int id, String name, String image) {  
  33.         this.id = id;  
  34.         this.name = name;  
  35.         this.image = image;  
  36.     }  
  37.     public Contact(){  
  38.           
  39.     }  
  40. }  

step5:写一个应用的service层,用于对javabean进行操作  cn.roco.data.service.ContactService.java

[java] view plaincopy
  1. package cn.roco.data.service;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.InputStream;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.URL;  
  8. import java.util.ArrayList;  
  9. import java.util.List;  
  10.   
  11. import org.xmlpull.v1.XmlPullParser;  
  12.   
  13. import android.net.Uri;  
  14. import android.util.Xml;  
  15.   
  16. import cn.roco.data.domain.Contact;  
  17. import cn.roco.data.utils.MD5;  
  18.   
  19. public class ContactService {  
  20.     /** 
  21.      * 获取联系人数据 
  22.      *  
  23.      * @return 
  24.      * @throws Exception 
  25.      */  
  26.     public static List<Contact> getContacts() throws Exception {  
  27.         String path = "http://192.168.1.100:8080/Hello/contact.xml";  
  28.         HttpURLConnection connection = (HttpURLConnection) new URL(path)  
  29.                 .openConnection();  
  30.         connection.setConnectTimeout(5000);  
  31.         connection.setRequestMethod("GET");  
  32.         if (connection.getResponseCode() == 200) {  
  33.             return parseXML(connection.getInputStream());  
  34.         }  
  35.         return null;  
  36.     }  
  37.     /**转化XML获取数据 
  38.      * 服务器端的xml文件如下。。。。。。 
  39.      * <?xml version="1.0" encoding="UTF-8"?> 
  40.         <contacts> 
  41.             <contact id="1"> 
  42.                 <name>Roco_1</name> 
  43.                 <image src="http://192.168.1.100:8080/Hello/images/1.png" /> 
  44.             </contact> 
  45.             ....... 
  46.         </contacts>*/  
  47.     private static List<Contact> parseXML(InputStream inputStream)  
  48.             throws Exception {  
  49.         List<Contact> contacts = new ArrayList<Contact>();  
  50.         Contact contact = null;  
  51.   
  52.         XmlPullParser pullParser = Xml.newPullParser();  
  53.         pullParser.setInput(inputStream, "UTF-8");  
  54.         int event = pullParser.getEventType();  
  55.         while (event != XmlPullParser.END_DOCUMENT) {  
  56.             switch (event) {  
  57.             case XmlPullParser.START_TAG:  
  58.                 if ("contact".equals(pullParser.getName())) {  
  59.                     contact = new Contact();  
  60.                     contact.setId(new Integer(pullParser.getAttributeValue(0)));  
  61.                 } else if ("name".equals(pullParser.getName())) {  
  62.                     contact.setName(pullParser.nextText());  
  63.                 } else if ("image".equals(pullParser.getName())) {  
  64.                     contact.setImage(pullParser.getAttributeValue(0));  
  65.                 }  
  66.                 break;  
  67.             case XmlPullParser.END_TAG:  
  68.                 if ("contact".equals(pullParser.getName())) {  
  69.                     contacts.add(contact);  
  70.                     contact = null;  
  71.                 }  
  72.             }  
  73.             event = pullParser.next();  
  74.         }  
  75.         return contacts;  
  76.     }  
  77.   
  78.     /** 
  79.      * 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来 
  80.      *  
  81.      * @param path 
  82.      *            图片路径 
  83.      * @return 
  84.      */  
  85.     public static Uri getImage(String imagePath, File cacheDir)  
  86.             throws Exception {  
  87.         //缓存文件的文件名用MD5进行加密  
  88.         File localFile = new File(cacheDir, MD5.getMD5(imagePath)  
  89.                 + imagePath.substring(imagePath.lastIndexOf(".")));   
  90.         if (localFile.exists()) {  
  91.             return Uri.fromFile(localFile);  
  92.         } else {  
  93.             HttpURLConnection connection = (HttpURLConnection) new URL(  
  94.                     imagePath).openConnection();  
  95.             connection.setConnectTimeout(5000);  
  96.             connection.setRequestMethod("GET");  
  97.             //将文件缓存起来  
  98.             if (connection.getResponseCode() == 200) {  
  99.                 FileOutputStream outputStream = new FileOutputStream(localFile);  
  100.                 InputStream inputStream = connection.getInputStream();  
  101.                 byte[] buffer = new byte[1024];  
  102.                 int len = 0;  
  103.                 while ((len = inputStream.read(buffer)) != -1) {  
  104.                     outputStream.write(buffer, 0, len);  
  105.                 }  
  106.                 inputStream.close();  
  107.                 outputStream.close();  
  108.                 return Uri.fromFile(localFile);  
  109.             }  
  110.         }  
  111.         return null;  
  112.     }  
  113. }  


step6:写一个Adapter用于对ListView进行数据更新 cn.roco.data.adapter.ContactAdapter.java

[java] view plaincopy
  1. package cn.roco.data.adapter;  
  2.   
  3. import java.io.File;  
  4. import java.util.List;  
  5. import cn.roco.data.R;  
  6. import cn.roco.data.domain.Contact;  
  7. import cn.roco.data.service.ContactService;  
  8. import android.content.Context;  
  9. import android.net.Uri;  
  10. import android.os.AsyncTask;  
  11. import android.os.Handler;  
  12. import android.os.Message;  
  13. import android.view.LayoutInflater;  
  14. import android.view.View;  
  15. import android.view.ViewGroup;  
  16. import android.widget.BaseAdapter;  
  17. import android.widget.ImageView;  
  18. import android.widget.TextView;  
  19. /**适配器,用于更新View*/  
  20. public class ContactAdapter extends BaseAdapter {  
  21.     private List<Contact> data;  
  22.     private int listviewItem;  
  23.     private File cache;  
  24.     /** 
  25.      * LayoutInflater的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout文件夹下的xml布局文件,并且实例化! 
  26.      * 而 findViewById()是找具体某一个xml下的具体 widget控件(如:Button,TextView等)。 
  27.      */  
  28.     private LayoutInflater layoutInflater;  
  29.   
  30.     public ContactAdapter(Context context, List<Contact> data,  
  31.             int listviewItem, File cache) {  
  32.         this.data = data;  
  33.         this.listviewItem = listviewItem;  
  34.         this.cache = cache;  
  35.         this.layoutInflater = (LayoutInflater) context  
  36.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);//取得xml里定义的view  
  37.         /*** 
  38.          * getSystemService()是Android很重要的一个API,它是Activity的一个方法, 
  39.          * 根据传入的NAME来取得对应的Object,然后转换成相应的服务对象。以下介绍系统相应的服务。  
  40.          *  传入的Name                     返回的对象                   说明  
  41.             WINDOW_SERVICE              WindowManager           管理打开的窗口程序  
  42.             LAYOUT_INFLATER_SERVICE     LayoutInflater          取得xml里定义的view  
  43.             ACTIVITY_SERVICE            ActivityManager         管理应用程序的系统状态  
  44.             POWER_SERVICE               PowerManger             电源的服务  
  45.             ALARM_SERVICE               AlarmManager            闹钟的服务  
  46.             NOTIFICATION_SERVICE        NotificationManager     状态栏的服务  
  47.             KEYGUARD_SERVICE            KeyguardManager         键盘锁的服务  
  48.             LOCATION_SERVICE            LocationManager         位置的服务,如GPS  
  49.             SEARCH_SERVICE              SearchManager           搜索的服务  
  50.             VEBRATOR_SERVICE            Vebrator                手机震动的服务  
  51.             CONNECTIVITY_SERVICE        Connectivity            网络连接的服务  
  52.             WIFI_SERVICE                WifiManager             Wi-Fi服务  
  53.             TELEPHONY_SERVICE           TeleponyManager         电话服务  
  54.  
  55.          */  
  56.     }  
  57.   
  58.     /** 得到数据的总数 */  
  59.     @Override  
  60.     public int getCount() {  
  61.         return data.size();  
  62.     }  
  63.   
  64.     /** 根据数据索引,得到集合中所对应的数据 */  
  65.     @Override  
  66.     public Object getItem(int position) {  
  67.         return data.get(position);  
  68.     }  
  69.   
  70.     @Override  
  71.     public long getItemId(int position) {  
  72.         return position;  
  73.     }  
  74.   
  75.     @Override  
  76.     public View getView(int position, View convertView, ViewGroup parent) {  
  77.         ImageView imageView = null;  
  78.         TextView textView = null;  
  79.           
  80.         if (convertView == null) {  
  81.             convertView = layoutInflater.inflate(listviewItem, null);  
  82.             imageView = (ImageView) convertView.findViewById(R.id.imageView);  
  83.             textView = (TextView) convertView.findViewById(R.id.textView);  
  84.             convertView.setTag(new DataWrapper(imageView, textView));//将内容包装起来以备以后使用  
  85.         } else {  
  86.             DataWrapper dataWrapper=(DataWrapper) convertView.getTag();//将包装类取出来  
  87.             //从包装类中取数据  
  88.             imageView=dataWrapper.getImageView();  
  89.             textView=dataWrapper.getTextView();  
  90.         }  
  91.         Contact contact=data.get(position);  
  92.         textView.setText(contact.getName());  
  93.         /**异步加载图片文件*/  
  94.         asynchImageLoad(imageView,contact.getImage());  
  95.         return convertView;  
  96.     }  
  97.       
  98.     /* 
  99.     //该方法会创建很多的线程,也会很耗资源 
  100.     private void asynchImageLoad(final ImageView imageView, final String imagePath) { 
  101.         final Handler handler=new Handler(){ 
  102.             @Override 
  103.             public void handleMessage(Message msg) {//运行在主线程中 
  104.                 Uri uri=(Uri) msg.obj; 
  105.                 if (uri!=null&&imageView!=null) { 
  106.                     imageView.setImageURI(uri); 
  107.                 } 
  108.             } 
  109.         }; 
  110.         Runnable runnable=new Runnable() { 
  111.             @Override 
  112.             public void run() { 
  113.                 try { 
  114.                     Uri uri=ContactService.getImage(imagePath, cache); 
  115.                     handler.sendMessage(handler.obtainMessage(10,uri)); 
  116.                 } catch (Exception e) { 
  117.                     e.printStackTrace(); 
  118.                 } 
  119.             } 
  120.         }; 
  121.         new Thread(runnable).start(); 
  122.     } 
  123.     */  
  124.       
  125.     /**异步加载图片文件*/  
  126.     private void asynchImageLoad(ImageView imageView, String imagePath) {  
  127.         AsycImageTask asycImageTask=new AsycImageTask(imageView);  
  128.         asycImageTask.execute(imagePath);  
  129.     }  
  130.     /** 
  131.      * 使用AsyncTask提高性能 
  132.      * 可选方法: 
  133.         1,  onprogressupdate(progress…) 可以使用进度条增加用户体验度。此方法在主线程执行,用户显示任务执行的进度。 
  134.         2,  onpreExecute()  这里是最新用户调用excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。 
  135.         3,  onCancelled()  用户调用取消时,要做的操作。 
  136.          
  137.          AsyncTask<Params, Progress, Result>  
  138.          AsyscTask定义了三种泛型类型params,progress和result. 
  139.          1,  params启动任务执行的输入参数,比如http请求的URL 
  140.          2,  progress后台任务执行的百分比 
  141.          3,  result后台执行任务最终返回的结果,比如String,比如我需要得到的list。 
  142.          
  143.             使用AsyncTask类,遵守的准则:1,  Task的实例必须在UI thread中创建;2,  Execute方法必须在UI thread中调用 
  144.             3,  不要手动的调用onPfreexecute(),onPostExecute(result)Doinbackground(params…),onProgressupdate(progress…)这几个方法; 
  145.             4,  该task只能被执行一次,否则多次调用时将会出现异常; 
  146.             AsyncTask的整个调用过程都是从execute方法开始的,一旦在主线程中调用execute方法,就可以通过onpreExecute方法, 
  147.             这是一个预处理方法,比如可以在这里开始一个进度框,同样也可以通过onprogressupdate方法给用户一个进度条的显示,增加用户体验; 
  148.             最后通过onpostexecute方法,相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果处理操作UI。 
  149.             此方法在主线程执行,任务执行的结果作为此方法的参数返回 
  150.      */  
  151.     private final class AsycImageTask extends AsyncTask<String, Integer, Uri>{  
  152.         private ImageView imageView;  
  153.         public AsycImageTask(ImageView imageView) {  
  154.             this.imageView=imageView;  
  155.         }  
  156.         /** 
  157.          *  后台执行,比较耗时的操作都可以放在这里。 
  158.             注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作 
  159.             ,通常需要较长的时间。在执行过程中可以调用 
  160.             Public progress(progress…)来更新任务的进度。 
  161.          */  
  162.         @Override  
  163.         protected Uri doInBackground(String... params) {//子线程中执行  
  164.             try {  
  165.                 return ContactService.getImage(params[0], cache);  
  166.             } catch (Exception e) {  
  167.                 e.printStackTrace();  
  168.             }  
  169.             return null;  
  170.         }  
  171.         /** 
  172.          * 相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果 
  173.          * 处理操作UI。此方法在主线程执行,任务执行的结果作为此方法的参数返回。 
  174.          */  
  175.         @Override  
  176.         protected void onPostExecute(Uri result) {//运行在主线程  
  177.             if (result!=null&&imageView!=null) {  
  178.                 imageView.setImageURI(result);  
  179.             }  
  180.         }  
  181.           
  182.     }  
  183.       
  184.     /**数据包装类*/  
  185.     private final class DataWrapper {  
  186.         private ImageView imageView;  
  187.         private TextView textView;  
  188.   
  189.         public ImageView getImageView() {  
  190.             return imageView;  
  191.         }  
  192.   
  193.         public TextView getTextView() {  
  194.             return textView;  
  195.         }  
  196.   
  197.         public DataWrapper(ImageView imageView, TextView textView) {  
  198.             this.imageView = imageView;  
  199.             this.textView = textView;  
  200.         }  
  201.     }  
  202.   
  203. }  


step7:应用的主程序  cn.roco.data.MainActivity.java

[java] view plaincopy
  1. package cn.roco.data;  
  2.   
  3. import java.io.File;  
  4. import java.util.List;  
  5.   
  6. import cn.roco.data.adapter.ContactAdapter;  
  7. import cn.roco.data.domain.Contact;  
  8. import cn.roco.data.service.ContactService;  
  9. import android.app.Activity;  
  10. import android.os.Bundle;  
  11. import android.os.Environment;  
  12. import android.os.Handler;  
  13. import android.widget.ListView;  
  14.   
  15. public class MainActivity extends Activity {  
  16.     private ListView listView;  
  17.     /**缓存文件*/  
  18.     private File cache;  
  19.       
  20.     /**接受消息,处理消息 ,此Handler会与当前主线程一块运行 
  21.      * 使用匿名内部类来复写Handler当中的handlerMessage()方法  */  
  22.     Handler handler = new Handler() {  
  23.         // 接受数据  
  24.         public void handleMessage(android.os.Message msg) {  
  25.             //设置适配器,将获取的数据使用适配器更新View  
  26.             listView.setAdapter(new ContactAdapter(MainActivity.this,  
  27.                     (List<Contact>) msg.obj, R.layout.listview_item, cache));  
  28.         };  
  29.     };  
  30.   
  31.     @Override  
  32.     public void onCreate(Bundle savedInstanceState) {  
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(R.layout.main);  
  35.         listView = (ListView) this.findViewById(R.id.listView);  
  36.         /**在SD卡中生成缓存目录*/  
  37.         cache = new File(Environment.getExternalStorageDirectory(), "cache");  
  38.         /**如果目录不存在就新建一个*/  
  39.         if (!cache.exists())  cache.mkdir();  
  40.               
  41.         new Thread(new Runnable() {  
  42.             @Override  
  43.             public void run() {  
  44.                 try {  
  45.                     //获取联系人数据  
  46.                     List<Contact> data= ContactService.getContacts();  
  47.                     // 向Handler发送消息,更新UI  
  48.                     handler.sendMessage(handler.obtainMessage(22, data));  
  49.                 } catch (Exception e) {  
  50.                     e.printStackTrace();  
  51.                 }  
  52.             }  
  53.         }).start();  
  54.     }  
  55.       
  56.     @Override  
  57.     protected void onDestroy() {  
  58.         /**清除缓存文件*/  
  59.         for (File file:cache.listFiles()) {  
  60.             file.delete();  
  61.         }  
  62.         cache.delete();  
  63.         super.onDestroy();  
  64.     }  
  65.       
  66. }  

step8:AndroidManifest.xml

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="cn.roco.data" android:versionCode="1" android:versionName="1.0">  
  4.     <uses-sdk android:minSdkVersion="8" />  
  5.       
  6.     <!-- 访问Internet权限 -->  
  7.     <uses-permission android:name="android.permission.INTERNET" />  
  8.     <!-- 在SD卡中创建和删除文件权限 -->  
  9.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  10.     <!-- 往SD卡中写入数据权限 -->  
  11.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
  12.   
  13.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  14.         <activity android:name=".MainActivity" android:label="@string/app_name">  
  15.             <intent-filter>  
  16.                 <action android:name="android.intent.action.MAIN" />  
  17.                 <category android:name="android.intent.category.LAUNCHER" />  
  18.             </intent-filter>  
  19.         </activity>  
  20.   
  21.     </application>  
  22. </manifest>  

step9:编写服务器端的代码,主要是一个contact.xml文件

[html] view plaincopy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <contacts>  
  3.     <contact id="1">  
  4.         <name>Roco_1</name>  
  5.         <image src="http://192.168.1.100:8080/Hello/images/1.png" />  
  6.     </contact>  
  7.     <contact id="2">  
  8.         <name>Roco_2</name>  
  9.         <image src="http://192.168.1.100:8080/Hello/images/2.png" />  
  10.     </contact>  
  11.     <contact id="3">  
  12.         <name>Roco_3</name>  
  13.         <image src="http://192.168.1.100:8080/Hello/images/3.png" />  
  14.     </contact>  
  15.     <contact id="4">  
  16.         <name>Roco_4</name>  
  17.         <image src="http://192.168.1.100:8080/Hello/images/4.png" />  
  18.     </contact>  
  19.     <contact id="5">  
  20.         <name>Roco_5</name>  
  21.         <image src="http://192.168.1.100:8080/Hello/images/5.png" />  
  22.     </contact>  
  23.     <contact id="6">  
  24.         <name>Roco_6</name>  
  25.         <image src="http://192.168.1.100:8080/Hello/images/6.png" />  
  26.     </contact>  
  27.     <contact id="7">  
  28.         <name>Roco_7</name>  
  29.         <image src="http://192.168.1.100:8080/Hello/images/7.png" />  
  30.     </contact>  
  31.     <contact id="8">  
  32.         <name>Roco_8</name>  
  33.         <image src="http://192.168.1.100:8080/Hello/images/8.png" />  
  34.     </contact>  
  35.     <contact id="9">  
  36.         <name>Roco_9</name>  
  37.         <image src="http://192.168.1.100:8080/Hello/images/9.png" />  
  38.     </contact>  
  39.     <contact id="10">  
  40.         <name>Roco_10</name>  
  41.         <image src="http://192.168.1.100:8080/Hello/images/10.png" />  
  42.     </contact>  
  43.     <contact id="11">  
  44.         <name>Roco_11</name>  
  45.         <image src="http://192.168.1.100:8080/Hello/images/11.png" />  
  46.     </contact>  
  47.     <contact id="12">  
  48.         <name>Roco_12</name>  
  49.         <image src="http://192.168.1.100:8080/Hello/images/12.png" />  
  50.     </contact>  
  51.     <contact id="13">  
  52.         <name>Roco_13</name>  
  53.         <image src="http://192.168.1.100:8080/Hello/images/13.png" />  
  54.     </contact>  
  55.     <contact id="14">  
  56.         <name>Roco_14</name>  
  57.         <image src="http://192.168.1.100:8080/Hello/images/14.png" />  
  58.     </contact>  
  59.     <contact id="15">  
  60.         <name>Roco_15</name>  
  61.         <image src="http://192.168.1.100:8080/Hello/images/15.png" />  
  62.     </contact>  
  63.     <contact id="16">  
  64.         <name>Roco_16</name>  
  65.         <image src="http://192.168.1.100:8080/Hello/images/16.png" />  
  66.     </contact>  
  67.     <contact id="17">  
  68.         <name>Roco_17</name>  
  69.         <image src="http://192.168.1.100:8080/Hello/images/17.png" />  
  70.     </contact>  
  71.     <contact id="18">  
  72.         <name>Roco_18</name>  
  73.         <image src="http://192.168.1.100:8080/Hello/images/18.png" />  
  74.     </contact>  
  75.     <contact id="19">  
  76.         <name>Roco_19</name>  
  77.         <image src="http://192.168.1.100:8080/Hello/images/19.png" />  
  78.     </contact>  
  79.     <contact id="20">  
  80.         <name>Roco_20</name>  
  81.         <image src="http://192.168.1.100:8080/Hello/images/20.png" />  
  82.     </contact>  
  83. </contacts>  

以及在images目录下放置了一些图片



step10:将项目部署到模拟器上运行效果如下图:

         

在SD卡中会生成缓存文件


当应用退出的时候,会将缓存文件删除



有了缓存文件,只要应用没有退出,即使联网不成功,也可以读取缓存中的图片文件

原创粉丝点击