閱讀734 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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="https://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="https://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="https://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 來獲取數據: https://pic.think-land.com/xmlall.php?

配合參數最後查詢的URL是: https://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 = "https://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. 顯示新聞列表內容

 

程序包下載:https://u.115.com/file/f5a9c4e698#MyNewsReader_L7_1.rar

最後更新:2017-04-02 17:51:23

  上一篇:go Android-ListView中嵌套(ListView)控件時的問題
  下一篇:go Android實戰技巧:如何在ListView中嵌套ListView