ANDROID 开发一个新闻阅读器之新闻列表

1.          功能描述

这一讲中我们将对如何实现新闻列表做一个详细的介绍,新闻列表会把所有我们从网上获取的新闻的标题显示给用户,用户通过阅读标题,选择自己想要查看的新闻,进入具体的新闻显示页。

下图是我们设计的样式,最上方的按钮栏这边不再多做介绍了,相信看过前几章的读者已经如何实现这个按钮栏了。

按钮栏下方就是新闻列表,里面会显示一个ImageView 和 一个 TextView

ImageView: 1张图片

TextView: 新闻标题

如果列表长度超出当前屏幕大小,可上下拖动该列表。

 

2.界面布局

在layout 目录下分别创建 news_result_list.xml 和 news_result_list_item.xml布局文件.

news_result_list.xml: 整个页面的布局,包括上放的按钮栏 和 下方的列表控件

news_result_list_item.xml:列表控件中 单个ITEM 的布局,所谓单个ITEM 就是类似如下图就是单个的ITEM

 

 

下面让我们先来看下news_result_list.xml 里面的代码:

 


 1 
 2  <?xml version="1.0" encoding="utf-8"?>
 3  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 4     android:orientation="vertical"
 5     android:layout_width="fill_parent"
 6     android:layout_height="fill_parent"
 7 android:background="@color/white">
 8 //按钮栏布局,上篇课程已经讲解过,这里不再多做介绍
 9   <RelativeLayout android:id="@+id/result_RelativeLayout01"
10     android:layout_width="fill_parent"
11     android:layout_height="wrap_content"
12     android:background="@color/yellow">
13     <Button android:id="@+id/result_back" //定义了一个新的 ID result_back
14             android:layout_width="wrap_content"
15             android:layout_height="wrap_content"
16             android:layout_alignParentLeft="true"
17             android:paddingLeft="2dip"
18             android:text="@string/back"/>
19 //定义了一个新的 ID result_collection
20  <Button android:id="@+id/result_collection"
21             android:layout_width="wrap_content"
22             android:layout_height="wrap_content"
23             android:layout_alignParentRight="true"
24             android:paddingRight="2dip"
25             android:text="@string/collection"/>  
26   </RelativeLayout>   
27  
28 // 开始定义ListView,给ListView的最外层定义一个LinearLayout 布局
29   <LinearLayout android:id="@+id/result_LinearLayout01"
30            android:layout_width="fill_parent"
31            android:layout_height="fill_parent"
32            android:padding="5dip"
33            android:orientation="vertical">   
34 // 定义一个RelativeLayout 布局
35            <RelativeLayout android:id="@+id/android:empty"
36               android:layout_width="fill_parent"
37               android:layout_height="wrap_content"  
38     xmlns:android="http://schemas.android.com/apk/res/android">
39 //定义一个TextView 用来显示诸如:数据读取中,不存在新闻数据 这类让用户了解现在软件运行状态的信息
40               <TextView android:id="@+id/newsResultListEmptyText"
41                   android:layout_width="fill_parent"
42                   android:gravity="center" //布局居中
43                   android:layout_height="100dip"
44                      //对应上层布局居中
45                   android:layout_centerInParent="true"                                  
46                   android:text="@string/wait_loading" //默认显示内容
47                   android:textColor="@color/black" //字体颜色
48                   android:textStyle="bold"> //字体样式
49               </TextView>
50            </RelativeLayout>
51 // 定义ListView 控件,ID 设为 newsResultList
52            <ListView android:id="@+id/newsResultList"
53               android:cacheColorHint="#00000000" //这个属性可以有效防止滑动过程中,ITEM 颜色变黑
54               android:dividerHeight="1dip" //2个ITEM 之间的间隔距离
55               android:scrollbars="none" //是否显示滑动条,默认是显示,我们这里设置成不显示
56               android:divider="@color/semi_black" //2个ITEM 之间间隔条的颜色
57               android:layout_width="fill_parent"
58               android:layout_height="fill_parent">
59            </ListView>
60     </LinearLayout>    
61    
62  </LinearLayout>   
63  


ListView 是整个ANDROID 中非常重要的一个内容,几乎每个应用程序都需要涌动啊 ListView,这里鉴于篇幅,我们只做和该应用相关的内容的介绍,稍后,我们会单独用一篇课程来讲解介绍ListView

这里我们只需要了解,定义使用ListView在xml布局文件中的常规写法就可以了。

 

在定义完整个页面的布局文件 news_result_list.xml 后,我就开始着手news_result_list_item.xml 文件,这个文件的布局就非常简单了, 因为它只需要标示一个ITEM 的内容,ListView会不断的使用这个布局来创建每个ITEM。

具体如下:

 


 1 <?xml version="1.0" encoding="utf-8"?>
 2  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:orientation="horizontal" //注意这里定义的是 horizontal 的布局,也就是横向的
 4     android:layout_width="fill_parent"
 5     android:layout_height="50dip"
 6     android:background="@color/white">
 7 //定义一个ImageView ID 为 result_newsImg
 8     <ImageView android:id="@+id/result_newsImg"
 9        android:layout_width="wrap_content"
10        android:layout_height="wrap_content"
11        android:layout_gravity="center_vertical" //设置为布局剧中
12        android:src="@drawable/news_icon"/> //图片指向的目录
13 //定义一个 TextView ID 为 result_newsImg
14     <TextView android:id="@+id/result_newsTitle"
15        android:layout_width="fill_parent"
16        android:layout_height="wrap_content"
17        android:layout_gravity="center_vertical" //设置为布局剧中
18        android:padding="5dip"
19        android:textSize="15px"
20        android:textColor="@color/black"
21        android:textStyle="bold"/> 
22  </LinearLayout>   
 

这样,前台的布局文件我们就完成了,接下来着手后台的逻辑实现

 

 

3.  后台逻辑层

首先,我们定义一个集成Activity 的class    newsResultListActivity.java

重写 onCreate 方法:

 

 

 

 

 

 

 

 

 

 

复制代码
 1 public String newsType = "0";  
 2  public Context mContext;
 3  
 4     public void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.news_result_list);
 7        
 8         mContext = newsResultListActivity.this;
 9        
10         Intent aIntent = getIntent();
11         Bundle aBundle = aIntent.getExtras();
12         if(aBundle != null){
13         //获取上一个Activity 传递过来的新闻类型参数
14          newsType = aBundle.getString(MyNewsReaderConstant.MAIN_NEWS_TYPE);
15         }       
16        
17         //显示一个loading框
18          startLoadingDialog();
19        
20         //获取页面上定义的控件资源,包括listview
21          findView();
22        
23         //开启一个线程用来获取网络新闻数据
24          Thread webThread = new Thread(new getWebData());
25         webThread.start();
26     }

上面的代码中多我们开启了一个新的线程用来从网络上获取新闻数据,因为这是一个比较耗时的动作,所以我们又在执行这个线程之前调用了一个方法 statLoadingDialog(), 用来显示一个loading的动画,这样用户就知道现在在读取数据,需要等待一段时间,

下面是这个方法的实现内容:

 

 

1 public ProgressDialog pd;
2  
3  public void startLoadingDialog(){
4     pd = ProgressDialog.show(newsResultListActivity.this, null, MyNewsReaderConstant.PROGRESS_ALERT_LOADING, true,true);
5 }

 

而方法fnidView 则获取页面控件资源,当然也包括ListView 控件

 

 1 public Button result_back, result_collection;
 2  //用来显示无新闻记录,或者请用户等待 一类的提示信息
 3  public TextView newsResultListEmptyText;
 4  public ListView newsResultList; //页面的ListView控件
 5   
 6  public void findView(){
 7       
 8        result_back = (Button)this.findViewById(R.id.result_back);
 9        result_collection = (Button)this.findViewById(R.id.result_collection);
10        newsResultListEmptyText = (TextView)this.findViewById(R.id.newsResultListEmptyText);
11        newsResultList = (ListView)this.findViewById(R.id.newsResultList);
12       
13     }
复制代码

 

这些都完成后就开启一个线程 getWebDate(),在这个线程内,我们通过定义在接口 getWebDataHelperI 中的 getNewsResultListByType()返回一个List,该List内保存有网络数据.


 1 protected static final int threadS1 = 0x2311;
 2  protected static final int threadF1 = 0x2312;
 3  public List<newsDataTO> dataList; //存放数据的List
 4  public getWebDataHelperI gwdhI; //实现网络功能的接口
 5   
 6  public class getWebData implements Runnable{
 7  
 8            @Override
 9            public void run() {
10               Message m1 = new Message();           
11                Message m2 = new Message();
12                m1.what = threadS1;
13                m2.what = threadF1;                          
14              
15               dataList = new ArrayList<newsDataTO>();
16               boolean sendErrorMsg = false;
17              
18               //searchValues 数组,用来存放网络查询参数
19                String[] searchColumns = {"type"};
20               String[] searchValues = {newsType};
21                  //实例化这个借口
22                gwdhI = new getWebDataHelperImpl();
23                  //调用该接口的实现方法,把 searchColumnns, searchValues作为参数
24                dataList = gwdhI.getNewsResultListByType(searchColumns, searchValues);      
25               //如果返回的List为空,发送错误消息
26                if(dataList == null || dataList.size() == 0){
27                   messageListener.sendMessage(m2);
28                   return;
29               }
30               //List不为空,发送正确消息
31                messageListener.sendMessage(m1);
32            }
33             
34       }

如果返回的List内有值的话,说明从网络上获取到了新闻的数据,然后发送消息 通知 Handler消息监听器 获取新闻数据成功,然后显示该新闻列表。如果返回的List 为空,则发送消息通知监听器 获取新闻数据失败,显示无法获取新闻的提示信息。

 

下面就是Handler 的代码:


 1 Handler messageListener = new Handler(){
 2         
 3          public void handleMessage(Message msg){
 4               switch(msg.what){
 5               case threadS1:
 6                   pd.dismiss(); //关闭loading框
 7                    displayNewsResult(); //显示新闻列表
 8                    break;
 9               case threadF1:
10                   pd.dismiss(); //关闭loading框
11 //显示未能查询到记录的信息
12      newsResultListEmptyText.setVisibility(View.VISIBLE);
13        //显示提示信息,该信息定义在string.xml中的serverConnectErrorMsg    newsResultListEmptyText.setText(getResources().getString(R.string.serverConnectErrorMsg));
14                    break;
15               }
16            }
17       };

里面有调用方法 displayNewsResult()来显示新闻列表, 这个方法里包括了自定义List,


 1 public void displayNewsResult(){
 2        //当有返回新闻数据时,提示信息不用显示 设置为不可见,这样用户就看不到页面上 '请等待' 这些提示
 3         newsResultListEmptyText.setVisibility(View.GONE);
 4        //自定义一个 Adapter
 5         newsResultListAdapter newsResultAdapter = new newsResultListAdapter(dataList, mContext);
 6        //将自定义的Adapter set进newsResultList,该List就是页面上的 ListView控件
 7  newsResultList.setAdapter(newsResultAdapter);
 8        //给ListView控件添加 onItemClickListener 事件,使用户点击ITEM 的时候能触发事件
 9         newsResultList.setOnItemClickListener(new OnItemClickListener(){
10            @Override
11            public void onItemClick(AdapterView<?> arg0, View arg1,
12                   int arg2, long arg3) {
13               // TODO Auto-generated method stub
14               
15            }
16           
17        });
18     }

上面就是一个显示自定义ListView的大致的框架,不过这时候还无法显示新闻列表,因为你会发现有2个地方我们还没有详细说明

l  newsResultListAdapter newsResultAdapter =

new newsResultListAdapter(dataList, mContext);

l  gwdhI.getNewsResultListByType(searchColumns, searchValues);   

 

 另外我们还需要定义一个数据结构用来存储新闻内容:

 

 

 1 public class newsDataTO {
 2     private long id; //唯一的ID
 3      private long newsId; //新闻的唯一的ID
 4      private String newsType; //新闻的类型
 5      private String newsTitle; //新闻的标题
 6      private String newsContent; //新闻的内容
 7     
 8     public long getId() {
 9        return id;
10     }
11     public void setId(long id) {
12        this.id = id;
13     }
14     public long getNewsId() {
15        return newsId;
16     }
17     public void setNewsId(long newsId) {
18        this.newsId = newsId;
19     }
20     public String getNewsType() {
21        return newsType;
22     }
23     public void setNewsType(String newsType) {
24        this.newsType = newsType;
25     }
26     public String getNewsTitle() {
27        return newsTitle;
28     }
29     public void setNewsTitle(String newsTitle) {
30        this.newsTitle = newsTitle;
31     }
32     public String getNewsContent() {
33        return newsContent;
34     }
35     public void setNewsContent(String newsContent) {
36        this.newsContent = newsContent;
37     }
38  
39 }

A. gwdhI.getNewsResultListByType(searchColumns, searchValues); 网络数据的获取

 

调用getNewsResultListByType() 我们传入了2个参数,一个是 searchColumns 用来存放网络查询字段的名称,另一个是searchValues 存放查询字段对应的值,这2个参数都是数组类型,见代码:

 

1             //searchValues 数组,用来存放网络查询参数
2                String[] searchColumns = {"type"};
3               String[] searchValues = {newsType};

说明我们传入了一个 查询的字段type, 其值是newsType。

 

我们先创建接口文件:

 

getWebDataHelperI.java 下面定义一个接口 getNewsResultListByType


1 import java.util.List;
2  import com.thinkland.demo.mnr.data.newsDataTO;
3  
4  public interface getWebDataHelperI {
5  
6     public List<newsDataTO> getNewsResultListByType(String[] searchColumns, String[] searchValues);
7  
8 }

接口内方法的实现:

 

1.  我们先处理传入的参数 String[] searchColumns 和 String[] searchValues

分别循环着2个数组,将获得的值,键值配对。在我们的示例代码中,最后得到的因该是type=4

下面是具体的代码

 


 1 Map searchMap = new HashMap();
 2        //如果查询字段存放数组内有值,将 hashMap 的键设置成 查询的字段名字
 3         if(searchColumns != null){
 4            for(int i = 0; i< searchColumns.length; i++){
 5               searchMap.put(searchColumns[i], "");
 6            }     
 7        }
 8        //如果查询具体内容存放数组有值,将该值按顺序放入searchMap 的值中
 9         if(searchValues != null){
10            for(int ii = 0; ii< searchValues.length; ii++){
11               //这里防止 value 超出了searchColumns 数组的范围
12                if(ii <= searchColumns.length){
13                   searchMap.put(searchColumns[ii], searchValues[ii]);
14               }            
15            }
16        }
17       
18        StringBuffer sb = new StringBuffer();
19        sb.append("");
20        Iterator it = searchMap.entrySet().iterator();
21        while (it.hasNext()) {
22            Entry entry = (java.util.Map.Entry) it.next();
23            sb.append("&");
24            sb.append(entry.getKey()); // 返回与此项对应的键
25             sb.append("=");
26            sb.append(entry.getValue()); // 返回与此项对应的值
27   
28        }
29        String searchUrlValue = sb.toString();
30        if(searchUrlValue != null && !"".equals(searchUrlValue)){
31            searchUrlValue = searchUrlValue.substring(1); //跳过开头的&符号,最后产生的查询参数因该是类似: parameter1=a&parameter2=b
32         }
33  
复制代码

 

我们使用测试用的URL 来获取数据: http://pic.think-land.com/xmlall.php?

配合参数最后查询的URL是: http://pic.think-land.com/xmlall.php?type=4

 

 

认识URL是进行网络编程的第一步。java.net.URL提供了丰富的URL构建方式,并可以通过java.net.URL来获取资源。类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

我们可以通过下面的方法来获取URL指定的资源

1 URL connectUrl = new URL(“http://pic.think-land.com/xmlall.php?type=4”);
2  //返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
3  URLConnection uc = connectUrl.openConnection();
4  //打开的连接读取的输入流。
5  InputStream is = uc.getInputStream();
 


返回的是XML 格式的stream

 

 

解析返回的XML,每个节点<row></row>内的内容就是一笔新闻资料,通过解析每一笔新闻内容都会保存进 newsDataTO 对象,然后add进List:

 

复制代码
 1 
 2 DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
 3             DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();          
 4            
 5             ByteArrayOutputStream   baos   =   new   ByteArrayOutputStream();
 6            int   i=-1;
 7            while((i=is.read())!=-1){
 8            baos.write(i);
 9            }
10            String returnIs = baos.toString().trim();       
11  //         Log.v("test", "-------------------- parseXML_rg  returnIs is : \n" + returnIs);
12             InputStream iis = new ByteArrayInputStream(returnIs.getBytes());
13            
14            
15            
16             Document doc = docBuilder.parse(iis);
17             doc.getDocumentElement ().normalize ();
18            
19             NodeList listOfTeams = doc.getElementsByTagName("row");
20                              
21             for(int s=0; s<listOfTeams.getLength() ; s++){         
22                 Node firstTeamNode = listOfTeams.item(s);              
23                 if(firstTeamNode.getNodeType() == Node.ELEMENT_NODE){
24  
25                     Element firstTeamElement = (Element)firstTeamNode;
26                     //实例化一个新的newsDataTO
27                       newsDataTO ndTO = new newsDataTO();
28                     //通过节点获取到值,新闻的ID
29                       String id = getValueByElement(firstTeamElement, "id");
30                     //通过节点获取到值,新闻的标题
31                       String newsTitle = getValueByElementAfterUtf(firstTeamElement,"title");
32                     //保存进数据结构,通过set方法
33                       ndTO.setId(Integer.parseInt(id));
34                      ndTO.setNewsId(Integer.parseInt(id));
35                      ndTO.setNewsTitle(newsTitle);
36                     //将该数据结构添加进list
37                       dataList.add(ndTO);
38                 }
39             }

通过解析XML 里的节点来获取对应节点内存放的值。

这里需要注意的是如果值是中文字符的话,通常需要对字符进行一些编码,解码的处理,所以我们定义了2个解析节点的方法来处理不同的情况:


 1 /**
 2      * 根据节点获取内容
 3      * @param element
 4      * @param tagName
 5      * @return String
 6 */
 7     private String getValueByElement(Element element, String tagName){
 8        String returnValue = "";
 9         
10         NodeList firstNameList = element.getElementsByTagName(tagName);
11         Element firstNameElement = (Element)firstNameList.item(0);        
12         NodeList textList = firstNameElement.getChildNodes();  
13         if(textList != null && (Node)textList.item(0)== null){
14              returnValue = "";
15         }else if(textList != null && ((Node)textList.item(0)).getNodeValue() != null){
16             returnValue =  ((Node)textList.item(0)).getNodeValue().trim();
17         }
18         return returnValue;
19     }
20    
21     /**
22      * 根据节点获取内容,并对获取的值做 UTF-8 的编码处理,一般针对中文
23      * @param element 节点对象
24      * @param tagName 节点名字
25      * @return String
26 */
27     private String getValueByElementAfterUtf(Element element, String tagName){
28        String returnValue = "";
29        NodeList firstNameList = element.getElementsByTagName(tagName);
30        Element firstNameElement = (Element)firstNameList.item(0);        
31        NodeList textList = firstNameElement.getChildNodes();  
32        if(textList != null && ((Node)textList.item(0)).getNodeValue() != null){
33        try {
34  //对该节点下的字节流进行 utf-8 解码
35             returnValue = new String( ((Node)textList.item(0)).getNodeValue().getBytes(), "utf-8");
36        } catch (UnsupportedEncodingException e) {
37            e.printStackTrace();
38        } catch (DOMException e) {
39            e.printStackTrace();
40        }
41        }
42        return returnValue;
43     }

下面是完整的代码:


  1 import java.io.ByteArrayInputStream;
  2  import java.io.ByteArrayOutputStream;
  3  import java.io.InputStream;
  4  import java.io.UnsupportedEncodingException;
  5  import java.net.URL;
  6  import java.util.ArrayList;
  7  import java.util.HashMap;
  8  import java.util.Iterator;
  9  import java.util.List;
 10  import java.util.Map;
 11  import java.util.Map.Entry;
 12  
 13  import javax.xml.parsers.DocumentBuilder;
 14  import javax.xml.parsers.DocumentBuilderFactory;
 15  
 16  import org.w3c.dom.DOMException;
 17  import org.w3c.dom.Document;
 18  import org.w3c.dom.Element;
 19  import org.w3c.dom.Node;
 20  import org.w3c.dom.NodeList;
 21  import org.xml.sax.SAXException;
 22  import org.xml.sax.SAXParseException;
 23  
 24  import android.util.Log;
 25  
 26  import com.thinkland.demo.mnr.data.newsDataTO;
 27  
 28  public class getWebDataHelperImpl implements getWebDataHelperI{
 29  
 30    public List<newsDataTO> getNewsResultListByType(String[] searchColumns, String[] searchValues) {
 31       
 32        //测试用URL 地址
 33         String netUrl = "http://pic.think-land.com/xmlall.php?";
 34       
 35        try{
 36        Map searchMap = new HashMap();
 37        //如果查询字段存放数组内有值,将 hashMap 的键设置成 查询的字段名字
 38         if(searchColumns != null){
 39            for(int i = 0; i< searchColumns.length; i++){
 40               searchMap.put(searchColumns[i], "");
 41            }     
 42        }
 43        //如果查询具体内容存放数组有值,将该值按顺序放入searchMap 的值中
 44         if(searchValues != null){
 45            for(int ii = 0; ii< searchValues.length; ii++){
 46               //这里防止 value 超出了searchColumns 数组的范围
 47                if(ii <= searchColumns.length){
 48                   searchMap.put(searchColumns[ii], searchValues[ii]);
 49               }            
 50            }
 51        }
 52       
 53        StringBuffer sb = new StringBuffer();
 54        sb.append("");
 55        Iterator it = searchMap.entrySet().iterator();
 56        while (it.hasNext()) {
 57            Entry entry = (java.util.Map.Entry) it.next();
 58            sb.append("&");
 59            sb.append(entry.getKey()); // 返回与此项对应的键
 60             sb.append("=");
 61            sb.append(entry.getValue()); // 返回与此项对应的值
 62   
 63        }
 64        String searchUrlValue = sb.toString();
 65        if(searchUrlValue != null && !"".equals(searchUrlValue)){
 66            searchUrlValue = searchUrlValue.substring(1); //跳过开头的&符号,最后产生的查询参数因该是类似: parameter1=a&parameter2=b
 67         }
 68        Log.v("getWebDataHelperImp", "---------------------- searchUrlValue : " + searchUrlValue);
 69        return netXMLPrase(netUrl + searchUrlValue);
 70  
 71        }catch(Exception e){
 72            e.printStackTrace();
 73        }
 74       
 75       return null;
 76     }
 77    
 78     public List netXMLPrase(String uriStr) throws Exception{
 79        try{
 80            List dataList = new ArrayList<newsDataTO>();
 81           
 82            URL connectUrl = new URL(uriStr);
 83            //返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
 84  URLConnection uc = connectUrl.openConnection();
 85  //打开的连接读取的输入流。
 86  InputStream is = uc.getInputStream();
 87            if(is == null){
 88               throw new Exception("netXMLPraseComicName - The inputStream is null");
 89            }
 90           
 91             DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
 92             DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();          
 93            
 94             ByteArrayOutputStream   baos   =   new   ByteArrayOutputStream();
 95            int   i=-1;
 96            while((i=is.read())!=-1){
 97            baos.write(i);
 98            }
 99            String returnIs = baos.toString().trim();        
100  //         Log.v("test", "-------------------- parseXML_rg  returnIs is : \n" + returnIs);
101             InputStream iis = new ByteArrayInputStream(returnIs.getBytes());
102            
103            
104            
105             Document doc = docBuilder.parse(iis);
106             doc.getDocumentElement ().normalize ();
107            
108             NodeList listOfTeams = doc.getElementsByTagName("row");
109                              
110             for(int s=0; s<listOfTeams.getLength() ; s++){         
111                 Node firstTeamNode = listOfTeams.item(s);               
112                 if(firstTeamNode.getNodeType() == Node.ELEMENT_NODE){
113  
114                     Element firstTeamElement = (Element)firstTeamNode;
115                    
116                      newsDataTO ndTO = new newsDataTO();
117  
118                      String id = getValueByElement(firstTeamElement, "id");
119                      String newsTitle = getValueByElementAfterUtf(firstTeamElement,"title");
120  
121                      ndTO.setId(Integer.parseInt(id));
122                      ndTO.setNewsId(Integer.parseInt(id));
123                      ndTO.setNewsTitle(newsTitle);
124  
125                      dataList.add(ndTO);
126                 }
127             }
128            
129             return dataList;
130  
131         }catch (SAXParseException err) {
132           throw new Exception(err);
133         } catch (SAXException e) {
134           Exception x = e.getException();
135           ((x == null) ? e : x).printStackTrace();
136           throw new Exception(e);
137         } catch (Exception t) {
138           t.printStackTrace();
139           throw new Exception(t);
140         }
141     }
142    
143    
144     /**
145      * 根据节点获取内容
146      * @param element
147      * @param tagName
148      * @return String
149 */
150     private String getValueByElement(Element element, String tagName){
151         String returnValue = "";
152         
153         NodeList firstNameList = element.getElementsByTagName(tagName);
154         Element firstNameElement = (Element)firstNameList.item(0);        
155         NodeList textList = firstNameElement.getChildNodes();  
156         if(textList != null && (Node)textList.item(0)== null){
157              returnValue = "";
158         }else if(textList != null && ((Node)textList.item(0)).getNodeValue() != null){
159             returnValue =  ((Node)textList.item(0)).getNodeValue().trim();
160         }
161         return returnValue;
162     }
163    
164     /**
165      * 根据节点获取内容,并对获取的值做 UTF-8 的编码处理,一般针对中文
166      * @param element
167      * @param tagName
168      * @return String
169 */
170     private String getValueByElementAfterUtf(Element element, String tagName){
171        String returnValue = "";
172         
173        NodeList firstNameList = element.getElementsByTagName(tagName);
174        Element firstNameElement = (Element)firstNameList.item(0);        
175        NodeList textList = firstNameElement.getChildNodes();  
176        if(textList != null && ((Node)textList.item(0)).getNodeValue() != null){
177        try {
178            returnValue = new String( ((Node)textList.item(0)).getNodeValue().getBytes(), "utf-8");
179        } catch (UnsupportedEncodingException e) {
180            e.printStackTrace();
181        } catch (DOMException e) {
182            e.printStackTrace();
183        }
184        }
185        return returnValue;
186     }
187  
188  
189 }

B. 自定义新闻列表

newsResultListAdapter newsResultAdapter =

new newsResultListAdapter(dataList, mContext);

 

com.thinkland.demo.mnr.helper下新建一个类 newsResultListAdapter.java

继承 BaseAdapter,代码如下:


 1 import java.util.List;
 2  import com.thinkland.demo.mnr.R;
 3  import com.thinkland.demo.mnr.data.newsDataTO;
 4  import android.content.Context;
 5  import android.view.LayoutInflater;
 6  import android.view.View;
 7  import android.view.ViewGroup;
 8  import android.widget.BaseAdapter;
 9  import android.widget.TextView;
10  
11  public class newsResultListAdapter extends BaseAdapter{
12    
13     private String TAG = "newsResultListAdapter";
14     private LayoutInflater mInflater;
15     private List<newsDataTO> item;
16     private Context context;
17    
18     public newsResultListAdapter(List<newsDataTO> item, Context context) {
19        super();
20          //从给定的context中获取 LayoutInflater
21         mInflater = LayoutInflater.from(context);
22        this.item = item;
23        this.context = context;
24     }
25  
26     //item 的数量
27      public int getCount() {
28        return item.size();
29     }
30  
31     //获取item的实例对象,参数position通常都是指当前item的id
32      public newsDataTO getItem(int position) {
33        return item.get(position);
34     }
35  
36     //获取当前item 的id
37      public long getItemId(int position) {
38        return position;
39     }
40  
41  
42     //实例化这个adapter时传入要显示的数据,然后用getView来显示每一个ListView的item
43      public View getView(int position, View convertView, ViewGroup parent) {
44        //将 news_result_list_item 转换为 view
45         if(convertView == null) {
46            convertView = mInflater.inflate(R.layout.news_result_list_item, null);
47        }
48        //获取 view里的 TextView 
49         TextView newsTitle = (TextView) convertView.findViewById(R.id.result_newsTitle);
50         //获取对应的 newsDataTO
51         newsDataTO newsDatato = (newsDataTO)getItem(position);
52        //将存放在 该数据结构中的 新闻标题 在页面布局上显示
53         newsTitle.setText(newsDatato.getNewsTitle());
54  
55        return convertView;
56      }
57  
58 }
59  

adapter中最重要的是getView

通过重写BaseAdapter中的方法,在实例化这个adapter时传入要显示的数据,然后用getView来显示每一个ListViewitem,通过实例化刚才建立的ViewconvertView 传入要显示在当前位置的数据项,然后返回处理完毕的view

 

 再回过头看 newsResultListActivity 中的方法 displayNewsResult()

1 newsResultListAdapter newsResultAdapter = new newsResultListAdapter(dataList, mContext);
2 newsResultList.setAdapter(newsResultAdapter);

 

就是将返回的 newsResultAdapter 实例化的对象赋值后显示在ListView newsResultList .


4.     Manifest 配置

a.  新增加一个Activity

1 <activity android:name=".newsResultListActivity"/>


b.  增加一个访问internet的权限

1 <uses-permission android:name="android.permission.INTERNET"/>

 

如果没有添加该权限,会出现如下的错误

catch (Exception e) 输出异常信息:
java.net.SocketException: Permission denied(maybe missing INTERNET permission)

 

5.     运行效果

a.  读取网络数据过程,显示loading……,同时提示用户耐心等待。

 

 

 

  1. 显示新闻列表内容

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值