现在的位置: 首页 > 综合 > 正文

Android异步从网络下载图片并且缓存图片到本地的demo

2013年12月11日 ⁄ 综合 ⁄ 共 8148字 ⁄ 字号 评论关闭

在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网络上加载XML资源,其中包括图片,我们要做的解析XML里面的数据,并且把图片缓存到本地一个cache目录里面,并且用一个自定义的Adapter去填充到LIstView,demo运行效果见下图:


通过这个demo,要学会有一下几点

1.怎么解析一个XML

2.demo中用到的缓存图片到本地一个临时目录的思想是怎样的?

3.AsyncTask类的使用,因为要去异步的加载数据,就必须开启线程,但是在开启线程的时有时候不能很好的控制线程的数量,线程数量太大的时候手机会很快被卡死 这里就采用AsynsTask类的去解决这个问题,这个类里面封装了线程池的技术,从而保证不会因开启过多的线程而消耗太多的资源

4.本demo中的Handler类的使用情况 5.自定义adapter的使用 

下面是demo中的Activity。

01 public
class
MainActivity extends
Activity {
02     protected
static final
int
SUCCESS_GET_CONTACT = 0;
03     private
ListView mListView;
04     private
MyContactAdapter mAdapter;
05     private
File cache;
06      
07     private
Handler mHandler = new
Handler(){
08         public
void handleMessage(android.os.Message msg) {
09             if(msg.what == SUCCESS_GET_CONTACT){
10                 List<Contact> contacts = (List<Contact>) msg.obj;
11                 mAdapter =
new MyContactAdapter(getApplicationContext(),contacts,cache);
12                 mListView.setAdapter(mAdapter);
13             }
14         };
15     };
16      
17     @Override
18     public
void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.main);
21          
22         mListView = (ListView) findViewById(R.id.listview);
23          
24         //创建缓存目录,系统一运行就得创建缓存目录的,
25         cache =
new File(Environment.getExternalStorageDirectory(),
"cache");
26          
27         if(!cache.exists()){
28             cache.mkdirs();
29         }
30          
31         //获取数据,主UI线程是不能做耗时操作的,所以启动子线程来做
32         new
Thread(){
33             public
void run() {
34                 ContactService service =
new ContactService();
35                 List<Contact> contacts =
null;
36                 try
{
37                     contacts = service.getContactAll();
38                 }
catch (Exception e) {
39                     e.printStackTrace();
40                 }
41                 //子线程通过Message对象封装信息,并且用初始化好的,
42                 //Handler对象的sendMessage()方法把数据发送到主线程中,从而达到更新UI主线程的目的
43                 Message msg =
new Message();
44                 msg.what = SUCCESS_GET_CONTACT;
45                 msg.obj = contacts;
46                 mHandler.sendMessage(msg);
47             };
48         }.start();
49     }
50      
51     @Override
52     protected
void onDestroy() {
53         super.onDestroy();
54         //清空缓存
55         File[] files = cache.listFiles();
56         for(File file :files){
57             file.delete();
58         }
59         cache.delete();
60     }
61 }
  Activity中,注意以下几点, 
1.初始化了一个缓存目录,这个目录最好是应用开启就去创建好,为手续缓存图片做准备,在这里把数据存放在SDCard上 
2.要去服务器加载数据,这个耗时操作最好是去开启线程加载数据,加载完毕后去异步的更新UI线程,利用Handler机制能很好的解决这个问题, 
3.最后退出应用的时候,要删掉缓存目录和目录里面的数据,避免给手机制造很多的垃圾文件 
下面就是一个Service类了, 
01 public
class
ContactService {
02  
03     /**
04      * 从服务器上获取数据
05      */
06     public
List<Contact> getContactAll() throws
Exception {
07         List<Contact> contacts =
null;
08         String Parth =
"http://192.168.1.103:8080/myweb/list.xml";
09         URL url =
new URL(Parth);
10         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
11         conn.setConnectTimeout(3000);
12         conn.setRequestMethod("GET");
13         if
(conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
14             InputStream is = conn.getInputStream();
15             // 这里获取数据直接放在XmlPullParser里面解析
16             contacts = xmlParser(is);
17             return
contacts;
18         }
else {
19             return
null;
20         }
21     }
22  
23     // 这里并没有下载图片下来,而是把图片的地址保存下来了
24     private
List<Contact> xmlParser(InputStream is) throws
Exception {
25         List<Contact> contacts =
null;
26         Contact contact =
null;
27         XmlPullParser parser = Xml.newPullParser();
28         parser.setInput(is,
"UTF-8");
29         int
eventType = parser.getEventType();
30         while
((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
31             switch
(eventType) {
32             case
XmlPullParser.START_TAG:
33                 if
(parser.getName().equals("contacts")) {
34                     contacts =
new ArrayList<Contact>();
35                 }
else if
(parser.getName().equals("contact")) {
36                     contact =
new Contact();
37                     contact.setId(Integer.valueOf(parser.getAttributeValue(0)));
38                 }
else if
(parser.getName().equals("name")) {
39                     contact.setName(parser.nextText());
40                 }
else if
(parser.getName().equals("image")) {
41                     contact.setImage(parser.getAttributeValue(0));
42                 }
43                 break;
44  
45             case
XmlPullParser.END_TAG:
46                 if
(parser.getName().equals("contact")) {
47                     contacts.add(contact);
48                 }
49                 break;
50             }
51         }
52         return
contacts;
53     }
54  
55     /*
56      * 从网络上获取图片,如果图片在本地存在的话就直接拿,如果不存在再去服务器上下载图片
57      * 这里的path是图片的地址
58      */
59     public
Uri getImageURI(String path, File cache) throws
Exception {
60         String name = MD5.getMD5(path) + path.substring(path.lastIndexOf("."));
61         File file =
new File(cache, name);
62         // 如果图片存在本地缓存目录,则不去服务器下载
63         if
(file.exists()) {
64             return
Uri.fromFile(file);//Uri.fromFile(path)这个方法能得到文件的URI
65         }
else {
66             // 从网络上获取图片
67             URL url =
new URL(path);
68             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
69             conn.setConnectTimeout(5000);
70             conn.setRequestMethod("GET");
71             conn.setDoInput(true);
72             if
(conn.getResponseCode() == 200) {
73  
74                 InputStream is = conn.getInputStream();
75                 FileOutputStream fos =
new FileOutputStream(file);
76                 byte[] buffer =
new byte[1024];
77                 int
len = 0;
78                 while
((len = is.read(buffer)) != -1) {
79                     fos.write(buffer,
0, len);
80                 }
81                 is.close();
82                 fos.close();
83                 // 返回一个URI对象
84                 return
Uri.fromFile(file);
85             }
86         }
87         return
null;
88     }
89 }
    Serivce类中,注意以下几点   
1.HttpURLConnection conn = (HttpURLConnection) url.openConnection();获取一个链接,从而进行通讯     
2.怎么利用XxmlPullPaser类去解析XML,从而把数据封装成对象   
3.getImageURI(String path, File cache) 这个方法具体实现   
4.Uri.fromFile(file);这个方法能够直接返回一个Uri来   
   下面是自定义的Adapter类,  
001 public
class
MyContactAdapter extends
BaseAdapter {
002  
003     protected
static final
int
SUCCESS_GET_IMAGE = 0;
004     private
Context context;
005     private
List<Contact> contacts;
006     private
File cache;
007     private
LayoutInflater mInflater;
008  
009     // 自己定义的构造函数
010     public
MyContactAdapter(Context context, List<Contact> contacts, File cache) {
011         this.context = context;
012         this.contacts = contacts;
013         this.cache = cache;
014  
015         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
016     }
017  
018     @Override
019     public
int getCount() {
020         return
contacts.size();
021     }
022  
023     @Override
024     public
Object getItem(int
position) {
025         return
contacts.get(position);
026     }
027  
028     @Override
029     public
long getItemId(int
position) {
030         return
position;
031     }
032  
033     @Override
034     public
View getView(int
position, View convertView, ViewGroup parent) {
035         // 1获取item,再得到控件
036         // 2 获取数据
037         // 3绑定数据到item
038         View view =
null;
039         if
(convertView != null) {
040             view = convertView;
041         }
else {
042             view = mInflater.inflate(R.layout.item,
null);
043         }
044  
045         ImageView iv_header = (ImageView) view.findViewById(R.id.iv_header);
046         TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
047  
048         Contact contact = contacts.get(position);
049  
050         // 异步的加载图片 (线程池 + Handler ) ---> AsyncTask
051         asyncloadImage(iv_header, contact.image);
052         tv_name.setText(contact.name);
053  
054         return
view;
055     }
056  
057     private
void asyncloadImage(ImageView iv_header, String path) {
058         ContactService service =
new ContactService();
059         AsyncImageTask task =
new AsyncImageTask(service, iv_header);
060         task.execute(path);
061     }
062  
063     private
final class
AsyncImageTask
extends
AsyncTask<String, Integer, Uri> {
064  
065         private
ContactService service;
066         private
ImageView iv_header;
067  
068         public
AsyncImageTask(ContactService service, ImageView iv_header) {
069             this.service = service;
070             this.iv_header = iv_header;
071         }
072

抱歉!评论已关闭.