ListView異步加載網絡數據

很多情況,我們需要從網絡加載數據,這個時候我們需要異步的方法去加載,並且實現數據緩存到本地的功能。

在主界面定義定義一個listview控件

main.xml代碼

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

在定義listview條目顯示的界面

listview_item.xml

  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.   
  7.     <ImageView   
  8.         android:layout_width="120dp"  
  9.         android:layout_height="120dp"  
  10.         android:id="@+id/imageView"  
  11.         />  
  12.   
  13.     <TextView   
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:textSize="18sp"  
  17.         android:textColor="#FFFFFF"  
  18.         android:id="@+id/textView"          
  19.         />  
  20. </LinearLayout>  

自定義適配器類,繼承BaseAdapter

  1. public class ContactAdapter extends BaseAdapter {  
  2.     private List<Contact> data;  
  3.     private int listviewItem;  
  4.     private File cache;  
  5.     LayoutInflater layoutInflater;  
  6.       
  7.     public ContactAdapter(Context context, List<Contact> data, int listviewItem, File cache) {  
  8.         this.data = data;  
  9.         this.listviewItem = listviewItem;  
  10.         this.cache = cache;  
  11.         layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  12.     }  
  13.     /** 
  14.      * 得到數據的總數 
  15.      */  
  16.     public int getCount() {  
  17.         return data.size();  
  18.     }  
  19.     /** 
  20.      * 根據數據索引得到集合所對應的數據 
  21.      */  
  22.     public Object getItem(int position) {  
  23.         return data.get(position);  
  24.     }  
  25.       
  26.     public long getItemId(int position) {  
  27.         return position;  
  28.     }  
  29. <span style="white-space:pre">  </span>//listview顯示每一個條目都會調用此方法  
  1. <span style="white-space:pre">  </span>//convertView: ListView考慮到性能,會對第一屏的顯示的條目進行緩存  
  1. public View getView(int position, View convertView, ViewGroup parent) {  
  2.     ImageView imageView = null;  
  3.     TextView textView = null;  
  4.       
  5.     if(convertView == null){  
  6.         convertView = layoutInflater.inflate(listviewItem, null);  
  7.         imageView = (ImageView) convertView.findViewById(R.id.imageView);  
  8.         textView = (TextView) convertView.findViewById(R.id.textView);  
  9.         convertView.setTag(new DataWrapper(imageView, textView));  
  10.     }else{  
  11.         DataWrapper dataWrapper = (DataWrapper) convertView.getTag();  
  12.         imageView = dataWrapper.imageView;  
  13.         textView = dataWrapper.textView;      
  14.     }  
  15.     Contact contact = data.get(position);  
  16.     textView.setText(contact.name);  
  17.     asyncImageLoad(imageView, contact.image);  
  18.     return convertView;  
  19. }  
  20.    private void asyncImageLoad(ImageView imageView, String path) {  
  21.     AsyncImageTask asyncImageTask = new AsyncImageTask(imageView);  
  22.     asyncImageTask.execute(path);  
  23.       
  24. }  
  25.      
  26.    private final class AsyncImageTask extends AsyncTask<String, Integer, Uri>{  
  27.     private ImageView imageView;  
  28.     public AsyncImageTask(ImageView imageView) {  
  29.         this.imageView = imageView;  
  30.     }  
  31.     protected Uri doInBackground(String... params) {//子線程中執行的  
  32.         try {  
  1. <span style="white-space:pre">              </span>//得到圖片的uri地址  
  2.                 return ContactService.getImage(params[0], cache);  
  3.             } catch (Exception e) {  
  4.                 e.printStackTrace();  
  5.             }  
  6.             return null;  
  7.         }  
  8.         protected void onPostExecute(Uri result) {//運行在主線程  
  9.             if(result!=null && imageView!= null)  
  10.                 imageView.setImageURI(result);  
  11.         }     
  12.     }  
  1. <span style="white-space:pre">  </span>//數據包裹類,如果顯示一個條目就去查找控件id的話,這樣會很耗性能  
  2.     private final class DataWrapper{  
  3.         public ImageView imageView;  
  4.         public TextView textView;  
  5.         public DataWrapper(ImageView imageView, TextView textView) {  
  6.             this.imageView = imageView;  
  7.             this.textView = textView;  
  8.         }  
  9.     }  
  10. }  

工具類

  1. public class ContactService {  
  2.   
  3.     /** 
  4.      * 獲取聯繫人 
  5.      * @return 
  6.      */  
  7.     public static List<Contact> getContacts() throws Exception{  
  8.         String path = "http://192.168.1.100:8080/web/list.xml";  
  9.         HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();  
  10.         conn.setConnectTimeout(5000);  
  11.         conn.setRequestMethod("GET");  
  12.         if(conn.getResponseCode() == 200){  
  13.             return parseXML(conn.getInputStream());  
  14.         }  
  15.         return null;  
  16.     }  
  17.     /** 
  18.      * 解析xml文件,並獲取所有聯繫人信息 
  19.      * @param xml 
  20.      * @return 
  21.      * @throws Exception 
  22.      */  
  23.     private static List<Contact> parseXML(InputStream xml) throws Exception{  
  24.         List<Contact> contacts = new ArrayList<Contact>();  
  25.         Contact contact = null;  
  26.         XmlPullParser pullParser = Xml.newPullParser();  
  27.         pullParser.setInput(xml, "UTF-8");  
  28.         int event = pullParser.getEventType();  
  29.         while(event != XmlPullParser.END_DOCUMENT){  
  30.             switch (event) {  
  31.             case XmlPullParser.START_TAG:  
  32.                 if("contact".equals(pullParser.getName())){  
  33.                     contact = new Contact();  
  34.                     contact.id = new Integer(pullParser.getAttributeValue(0));  
  35.                 }else if("name".equals(pullParser.getName())){  
  36.                     contact.name = pullParser.nextText();  
  37.                 }else if("image".equals(pullParser.getName())){  
  38.                     contact.image = pullParser.getAttributeValue(0);  
  39.                 }  
  40.                 break;  
  41.   
  42.             case XmlPullParser.END_TAG:  
  43.                 if("contact".equals(pullParser.getName())){  
  44.                     contacts.add(contact);  
  45.                     contact = null;  
  46.                 }  
  47.                 break;  
  48.             }  
  49.             event = pullParser.next();  
  50.         }  
  51.         return contacts;  
  52.     }  
  53.     /** 
  54.      * 獲取網絡圖片,如果圖片存在於緩存中,就返回該圖片,否則從網絡中加載該圖片並緩存起來 
  55.      * @param path 圖片路徑 
  56.      * @return 
  57.      */  
  58.     public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg  
  59.         File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf(".")));  
  60.         if(localFile.exists()){  
  61.             return Uri.fromFile(localFile);  
  62.         }else{  
  63.             HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();  
  64.             conn.setConnectTimeout(5000);  
  65.             conn.setRequestMethod("GET");  
  66.             if(conn.getResponseCode() == 200){  
  67.                 FileOutputStream outStream = new FileOutputStream(localFile);  
  68.                 InputStream inputStream = conn.getInputStream();  
  69.                 byte[] buffer = new byte[1024];  
  70.                 int len = 0;  
  71.                 while( (len = inputStream.read(buffer)) != -1){  
  72.                     outStream.write(buffer, 0, len);  
  73.                 }  
  74.                 inputStream.close();  
  75.                 outStream.close();  
  76.                 return Uri.fromFile(localFile);  
  77.             }  
  78.         }  
  79.         return null;  
  80.     }  
  81.   
  82. }  

主界面Activity的代碼

  1. public class MainActivity extends Activity {  
  2.     ListView listView;  
  3.     File cache;  
  4.       
  5.     Handler handler = new Handler(){  
  6.         public void handleMessage(Message msg) {  
  7.              listView.setAdapter(new ContactAdapter(MainActivity.this, (List<Contact>)msg.obj,   
  8.                      R.layout.listview_item, cache));  
  9.         }         
  10.     };  
  11.       
  12.     @Override  
  13.     public void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.         listView = (ListView) this.findViewById(R.id.listView);  
  17.           
  18.         cache = new File(Environment.getExternalStorageDirectory(), "cache");  
  19.         if(!cache.exists()) cache.mkdirs();  
  20.           
  21.         new Thread(new Runnable() {           
  22.             public void run() {  
  23.                 try {  
  24.                     List<Contact> data = ContactService.getContacts();  
  25.                     handler.sendMessage(handler.obtainMessage(22, data));  
  26.                 } catch (Exception e) {  
  27.                     e.printStackTrace();  
  28.                 }  
  29.             }  
  30.         }).start();         
  31.     }  
  32.   
  33.     @Override  
  34.     protected void onDestroy() {  
  35.         for(File file : cache.listFiles()){  
  36.             file.delete();  
  37.         }  
  38.         cache.delete();  
  39.         super.onDestroy();  
  40.     }  
  41.       
  42. }  

注意:由於應用訪問到網絡和sdcard,所以在功能清單文件中需要加入權限

  1. <uses-permission android:name="android.permission.INTERNET"/>  
  2.  <!-- 在SDCard中創建與刪除文件權限 -->  
  3. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  4. <!-- 往SDCard寫入數據權限 -->  
  5. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
發佈了54 篇原創文章 · 獲贊 7 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章