【ListViewJson】【MainActivity功能性分析,不讨论具体工具类的实现】【android解析json数据(包含对图片数据的异步缓存处理),并将其加载到listview中】
最近遇到了一个相当好、对初学者相当友善的项目,是描述如何将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一下。
下一篇博客具体讨论它的工具类的作用以及实现。