很多情况,我们需要从网络加载数据,这个时候我们需要异步的方法去加载,并且实现数据缓存到本地的功能。
在主界面定义定义一个listview控件
main.xml代码
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <ListView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:id="@+id/listView"/>
- </LinearLayout>
在定义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="120dp"
- android:layout_height="120dp"
- 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>
自定义适配器类,继承BaseAdapter
- public class ContactAdapter extends BaseAdapter {
- private List<Contact> data;
- private int listviewItem;
- private File cache;
- LayoutInflater layoutInflater;
- public ContactAdapter(Context context, List<Contact> data, int listviewItem, File cache) {
- this.data = data;
- this.listviewItem = listviewItem;
- this.cache = cache;
- layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
- /**
- * 得到数据的总数
- */
- public int getCount() {
- return data.size();
- }
- /**
- * 根据数据索引得到集合所对应的数据
- */
- public Object getItem(int position) {
- return data.get(position);
- }
- public long getItemId(int position) {
- return position;
- }
- <span style="white-space:pre"> </span>//listview显示每一个条目都会调用此方法
- <span style="white-space:pre"> </span>//convertView: ListView考虑到性能,会对第一屏的显示的条目进行缓存
- 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.imageView;
- textView = dataWrapper.textView;
- }
- Contact contact = data.get(position);
- textView.setText(contact.name);
- asyncImageLoad(imageView, contact.image);
- return convertView;
- }
- private void asyncImageLoad(ImageView imageView, String path) {
- AsyncImageTask asyncImageTask = new AsyncImageTask(imageView);
- asyncImageTask.execute(path);
- }
- private final class AsyncImageTask extends AsyncTask<String, Integer, Uri>{
- private ImageView imageView;
- public AsyncImageTask(ImageView imageView) {
- this.imageView = imageView;
- }
- protected Uri doInBackground(String... params) {//子线程中执行的
- try {
- <span style="white-space:pre"> </span>//得到图片的uri地址
- return ContactService.getImage(params[0], cache);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- protected void onPostExecute(Uri result) {//运行在主线程
- if(result!=null && imageView!= null)
- imageView.setImageURI(result);
- }
- }
- <span style="white-space:pre"> </span>//数据包裹类,如果显示一个条目就去查找控件id的话,这样会很耗性能
- private final class DataWrapper{
- public ImageView imageView;
- public TextView textView;
- public DataWrapper(ImageView imageView, TextView textView) {
- this.imageView = imageView;
- this.textView = textView;
- }
- }
- }
工具类
- public class ContactService {
- /**
- * 获取联系人
- * @return
- */
- public static List<Contact> getContacts() throws Exception{
- String path = "http://192.168.1.100:8080/web/list.xml";
- HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
- conn.setConnectTimeout(5000);
- conn.setRequestMethod("GET");
- if(conn.getResponseCode() == 200){
- return parseXML(conn.getInputStream());
- }
- return null;
- }
- /**
- * 解析xml文件,并获取所有联系人信息
- * @param xml
- * @return
- * @throws Exception
- */
- private static List<Contact> parseXML(InputStream xml) throws Exception{
- List<Contact> contacts = new ArrayList<Contact>();
- Contact contact = null;
- XmlPullParser pullParser = Xml.newPullParser();
- pullParser.setInput(xml, "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.id = new Integer(pullParser.getAttributeValue(0));
- }else if("name".equals(pullParser.getName())){
- contact.name = pullParser.nextText();
- }else if("image".equals(pullParser.getName())){
- contact.image = pullParser.getAttributeValue(0);
- }
- break;
- case XmlPullParser.END_TAG:
- if("contact".equals(pullParser.getName())){
- contacts.add(contact);
- contact = null;
- }
- break;
- }
- event = pullParser.next();
- }
- return contacts;
- }
- /**
- * 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
- * @param path 图片路径
- * @return
- */
- public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg
- File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf(".")));
- if(localFile.exists()){
- return Uri.fromFile(localFile);
- }else{
- HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
- conn.setConnectTimeout(5000);
- conn.setRequestMethod("GET");
- if(conn.getResponseCode() == 200){
- FileOutputStream outStream = new FileOutputStream(localFile);
- InputStream inputStream = conn.getInputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while( (len = inputStream.read(buffer)) != -1){
- outStream.write(buffer, 0, len);
- }
- inputStream.close();
- outStream.close();
- return Uri.fromFile(localFile);
- }
- }
- return null;
- }
- }
主界面Activity的代码
- public class MainActivity extends Activity {
- ListView listView;
- File cache;
- Handler handler = new Handler(){
- public void handleMessage(Message msg) {
- 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);
- cache = new File(Environment.getExternalStorageDirectory(), "cache");
- if(!cache.exists()) cache.mkdirs();
- new Thread(new Runnable() {
- public void run() {
- try {
- List<Contact> data = ContactService.getContacts();
- 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();
- }
- }
注意:由于应用访问到网络和sdcard,所以在功能清单文件中需要加入权限
- <uses-permission android:name="android.permission.INTERNET"/>
- <!-- 在SDCard中创建与删除文件权限 -->
- <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
- <!-- 往SDCard写入数据权限 -->
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>