標籤:
最近遇到了一個相當好、對初學者相當友善的項目,是描述如何將json資料解析,並載入到listview中。
但是個人認為以後所有類似功能的實現都可以使用這套工具。
項目也可以使用這套架構。
這個項目是處理每個news只有一個imgurl,應該考慮一下當imgurl數量不定的時候具體應該怎麼解決。
首先項目源碼結構如下:
項目下載連結:http://download.csdn.net/download/y562810463/8004245
在這個項目中的com.demo.app.common包完全可以應用在其它的項目中,而com.demo.api,com.demo.app等包也非常具有參考價值。
首先運行結果圖:
首先來說明一下程式的運行邏輯:
繼承Application類的appContext是應用真正的入口,但是appContext的onCreate方法調用了super.onCreate(),
所以從com.demo.app.ui的MainActivity進入。
MainActivity.java代碼如下以及邏輯分析:
package com.demo.app.ui;import java.util.List;import android.app.Activity;import android.app.ProgressDialog;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Button;import com.demo.app.AppContext;import com.demo.app.AppException;import com.demo.app.R;import com.demo.app.adapter.MainListViewAdapter;import com.demo.app.bean.News;import com.demo.app.bean.NewsList;import com.demo.app.common.UIHelper;import com.demo.app.widget.MyListView;public class MainActivity extends Activity { private MyListView listview; private List<News> newsList; private AppContext appContext;// 全域Context private MainListViewAdapter listViewAdapter; private ProgressDialog selectorDialog; private Button bt_news, bt_forum, bt_cartype, bt_favour, bt_more; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); appContext = (AppContext) getApplication(); // 網路連接判斷 if (!appContext.isNetworkConnected()) UIHelper.ToastMessage(this, R.string.network_not_connected); init(); initData(); } private void init() { bt_news = (Button) findViewById(R.id.bt_news); bt_forum = (Button) findViewById(R.id.bt_forum); bt_cartype = (Button) findViewById(R.id.bt_cartype); bt_favour = (Button) findViewById(R.id.bt_favour); bt_more = (Button) findViewById(R.id.bt_more); bt_news.setSelected(true); bt_news.setOnClickListener(onClick(bt_news)); bt_forum.setOnClickListener(onClick(bt_forum)); bt_cartype.setOnClickListener(onClick(bt_cartype)); bt_favour.setOnClickListener(onClick(bt_favour)); bt_more.setOnClickListener(onClick(bt_more)); listview = (MyListView) findViewById(R.id.news_listview); selectorDialog = ProgressDialog.show(this, null, "正在載入,請稍候...", true, false); } private View.OnClickListener onClick(final Button btn) { return new View.OnClickListener() { public void onClick(View v) { bt_news.setSelected(false); bt_forum.setSelected(false); bt_cartype.setSelected(false); bt_favour.setSelected(false); bt_more.setSelected(false); if (btn == bt_news) { bt_news.setSelected(true); } else if (btn == bt_forum) { bt_forum.setSelected(true); } else if (btn == bt_cartype) { bt_cartype.setSelected(true); } else if (btn == bt_favour) { bt_favour.setSelected(true); } else if (btn == bt_more) { bt_more.setSelected(true); } } }; } Handler mHandler = new Handler() { public void handleMessage(Message msg) { selectorDialog.cancel(); if (msg.what == 1) { newsList = (List<News>) msg.obj; listViewAdapter = new MainListViewAdapter(MainActivity.this, newsList); listview.setAdapter(listViewAdapter); } else if (msg.what == -1) { UIHelper.ToastMessage(MainActivity.this, "沒有資料"); } else if (msg.what == -2) { UIHelper.ToastMessage(MainActivity.this, R.string.xml_parser_failed); } } }; private void initData() { selectorDialog.show(); new Thread() { public void run() { Message msg = new Message(); boolean isRefresh = false; try { NewsList list = appContext.getNewsList(); if (list.getNewsCount() > 0) { msg.what = 1; msg.obj = list.getNewslist(); appContext.saveObject(list, "newslist_"); } else { msg.what = -1; } } catch (AppException e) { e.printStackTrace(); msg.what = -2; msg.obj = e; } mHandler.sendMessage(msg); } }.start(); }}
從MainActivity函數onCreate開始分析:
1、首先產生appContext,之後使用AppContext中定義的各種可能用到的方法。
appContext = (AppContext) getApplication();
2、進行網路判斷,其中UIHelper是一個工具類
if (!appContext.isNetworkConnected()) UIHelper.ToastMessage(this, R.string.network_not_connected);
3、執行init、initData方法,init方法比較簡單,關鍵是initData方法。
init();initData();
4、接下來分析 initData方法。因為initData方法與MainActivity中的handler相關,所以放在一起分析它們的作用。
Handler mHandler = new Handler() { public void handleMessage(Message msg) { selectorDialog.cancel(); if (msg.what == 1) { newsList = (List<News>) msg.obj; listViewAdapter = new MainListViewAdapter(MainActivity.this, newsList); listview.setAdapter(listViewAdapter); } else if (msg.what == -1) { UIHelper.ToastMessage(MainActivity.this, "沒有資料"); } else if (msg.what == -2) { UIHelper.ToastMessage(MainActivity.this, R.string.xml_parser_failed); } } }; private void initData() { selectorDialog.show(); new Thread() { public void run() { Message msg = new Message(); boolean isRefresh = false; try { NewsList list = appContext.getNewsList(); if (list.getNewsCount() > 0) { msg.what = 1; msg.obj = list.getNewslist(); appContext.saveObject(list, "newslist_"); } else { msg.what = -1; } } catch (AppException e) { e.printStackTrace(); msg.what = -2; msg.obj = e; } mHandler.sendMessage(msg); } }.start(); }
使用initdata方法去啟動一個線程,這個線程去獲得要載入的List<News>資料,通過使用appContext.getNewsList()方法。
而appContext.getNewsList()使用ApiClient.getNewsList()方法,ApiClient.getNewsList()方法中涉及如何通過網路擷取json字串並將json轉換為List<News>。
如果擷取List<News>成功的話,將其放到Message msg的域obj中,並將msg的域what設定為1.返還給handler。
注意:List<News>中的News圖片存的是一個url。
當handler獲得一個List<News>,它就建立 MainListViewAdapter適配器,而這個適配器將資料解析到listview中。需要注意的一點是:這個適配器中使用BitmapManager將圖片的url轉換為圖片。
另外需要注意一點的是:這個應用會將擷取到的資料存在緩衝中。而adapter會在getView中load一下。
下一篇部落格具體討論它的工具類的作用以及實現。
【ListViewJson】【MainActivity功能性分析,不討論具體工具類的實現】【android解析json資料(包含對圖片資料的非同步緩衝處理),並將其載入到listview中】