Android中使用网络访问来加载网上的内容,并将其解析出来加载到控件中,是一种很常见的操作。但是Android的UI线程(也就是主线程)中是不允许进行耗时操作的,因为耗时操作会阻塞主线程,影响用户体验。而访问网络同样是一个耗时操作,并且Android3.0以后是不允许在主线程中访问网络的,所以我们这里用Android封装好的AsyncTask类来完成这些耗时操作。
项目的目录结构如下:
AsyncTask是一个抽象类,实际上他是封装好的一个类,底层也是用handler和thread来实现的,我们首先应该定义一个类来继承它。AsyncTask的继承是包含三个泛型参数的,这点官方文档上有详细说明,第一个参数是要操作的数据的类型,我们一般传入一个String字符串来表示网址;第二个参数是想要展示进度条的时候,进度条的参数类型,一般指定为Integer;第三个参数是doInBackground()方法操作返回的数据类型,这里根据你想操作什么样的数据类型,就返回什么样的数据类型。注意:这三个参数不是一定要设置,用到了哪个设置哪个,不需要的参数可以设置为Void。
然后我们来看一下AsyncTask中的四个重要方法,基本上使用的时候我们都要重写这几个方法:
- onPreExecute():这个方法是在UI线程中调用,当我们调用AsyncTask的execute()方法的时候,此方法会首先执行,主要是完成一些初始化的操作,比如多用于初始化并显示进度条
- doInBackground(Params...):该方法在onPreExecute()方法调用结束之后调用,他的形参是一个可变参数,此方法在WorkThread也就是工作线程中完成,所有的耗时操作都要放在这个方法中执行,他可以将计算的结果返回到onPostExecute()方法中,同时在这里也可以调用publishProgress()方法来跳到onProgressUpdate()方法完成进度条刻度的更新,需要主要的是publishProgress()方法在WorkThread中完成,而onProgressUpdate()方法在UI线程中完成
- onProgressUpdate(Progress...):当调用了publishProgress()方法的时候,在UI线程被调用此方法,实现进度条的更新
- onPostExecute(Result):此方法在后台任务执行完后调用,在UI线程中执行,后台执行计算出的Result可以返回到此方法中,在此方法中可以更新UI界面组件
具体的AsyncTask的使用及源码分析请看这篇链接:http://blog.csdn.net/seu_calvin/article/details/52172248
大概看完了这四个方法,下面我们开始看看这次的Demo:
因为是想要从网络上获取json数据,所以要先准备一个接口,我的接口是时光网的:
http://api.m.mtime.cn/News/NewsList.api?pageIndex=1
为了得到这个接口中的Json格式的数据,我们先定义了一个HttpUtils类,在其中先定义了一个测试网络是否联通的类isNetConn(Context context)如下所示:
1 /**
2 * 获取网络状态
3 *
4 * @param context 上下文
5 * @return 联通状态
6 */
7 public static boolean isNetConn(Context context) {
8 //获取网络连接管理对象
9 ConnectivityManager manager = (ConnectivityManager) context.getSystemService(context.CONNECTIVITY_SERVICE);
10 //获取活跃状态的网络信息对象
11 NetworkInfo info = manager.getActiveNetworkInfo();
12 if (info != null) {
13 return info.isConnected(); //返回是否链接
14 } else {
15 return false;
16 }
17
18 }
又定义了一个返回byte数组downloadFromNet()方法,来获取数据的byte[]数组:
1 /**
2 * 获取网络上下载下来的数据的byte数组
3 *
4 * @param urlPath 网络URL路径
5 * @return 网络上获取的json字符串的byte数组形式
6 */
7 public static byte[] downloadFromNet(String urlPath) {
8 ByteArrayOutputStream baos = new ByteArrayOutputStream();
9 URL url = null;
10 try {
11 url = new URL(urlPath);
12 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
13 conn.setRequestMethod("GET");
14 conn.setConnectTimeout(5000);
15 conn.setReadTimeout(5000);
16 conn.setDoInput(true);
17 conn.connect();
18 if (conn.getResponseCode() == 200) {
19 InputStream is = conn.getInputStream();
20 int len;
21 byte b[] = new byte[1024];
22 //注意这里:is.read(b) 中的b数组一定要写,不然读取的数据不对
23 while ((len = is.read(b)) != -1) {
24 baos.write(b, 0, len);
25 baos.flush();
26 }
27 return baos.toByteArray();
28 }
29 return baos.toByteArray();
30 } catch (IOException e) {
31 e.printStackTrace();
32 }
33 return baos.toByteArray();
34 }
之所以返回byte[]数组类型,是方便我们下载其他东西的时候也可以使用。
获取到了json字符串,下一步就是将其解析出来,定义一个ParserJson方法,json字符串的解析相信大家应该都是了解的,因为这是Android中非常重要的一部分知识,这里就不再赘述,直接上代码:
json串对应的实体类:
1 package com.yztc.lx.asynctasklistview.com.yztc.lx.bean;
2
3 import java.util.List;
4
5 /**
6 * 外层JsonObject对象
7 * Created by Lx on 2016/8/10.
8 */
9
10 public class ShiGuang {
11
12 priv