实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23698511
今天继续对我们的csdn客户端未完成的功能进行实现,本篇博客接着客户端上显示csdn上的各类别下的的文章列表 (制作csdn app 三)继续完善我们的app。
今天的目标是:
1、对文章列表的下拉刷新,上拉加载。
2、没有网络的情况下,依然可以看到缓存在手机上的文章列表,以及上拉加载等。
大概效果图:
1、首先是对MainFragment.java编写,真对XListView实现下拉刷新和上拉加载。
@Override public void onRefresh() { new LoadDatasTask().execute(LOAD_REFREASH); } @Override public void onLoadMore() { new LoadDatasTask().execute(LOAD_MORE); }
我们对下拉刷新和上拉加载调用了一个异步任务,传入了操作的标识符,下面具体看个类:
/** * 记载数据的异步任务 * * @author zhy * */ class LoadDatasTask extends AsyncTask<Integer, Void, Integer> { @Override protected Integer doInBackground(Integer... params) { switch (params[0]) { case LOAD_MORE: loadMoreData(); break; case LOAD_REFREASH: return refreashData(); } return -1; } @Override protected void onPostExecute(Integer result) { switch (result) { case TIP_ERROR_NO_NETWORK: ToastUtil.toast(getActivity(), "没有网络连接!"); mAdapter.setDatas(mDatas); mAdapter.notifyDataSetChanged(); break; case TIP_ERROR_SERVER: ToastUtil.toast(getActivity(), "服务器错误!"); break; default: break; } mXListView.setRefreshTime(AppUtil.getRefreashTime(getActivity(), newsType)); mXListView.stopRefresh(); mXListView.stopLoadMore(); } }
可以看到,这个类中又使用了 loadMoreData();和 refreashData();
先看loadMoreData:
/** * 会根据当前网络情况,判断是从数据库加载还是从网络继续获取 */ public void loadMoreData() { // 当前数据是从网络获取的 if (isLoadingDataFromNetWork) { currentPage += 1; try { List<NewsItem> newsItems = mNewsItemBiz.getNewsItems(newsType, currentPage); mNewsItemDao.add(newsItems); mAdapter.addAll(newsItems); } catch (CommonException e) { e.printStackTrace(); } } else // 从数据库加载的 { currentPage += 1; List<NewsItem> newsItems = mNewsItemDao.list(newsType, currentPage); mAdapter.addAll(newsItems); } }
可以看到,如果当前app上的数据是从网络更新的即最新数据,我们会继续去网络加载下一页的数据,并且使用mNewsItemDao.add方法,插入我们的app的数据库中,供没有网络时使用。如果当前数据是缓存数据,我们则继续去数据库加载。
接下来看refreashData方法:
/** * 下拉刷新数据 */ public Integer refreashData() { if (NetUtil.checkNet(getActivity())) { isConnNet = true; // 获取最新数据 try { List<NewsItem> newsItems = mNewsItemBiz.getNewsItems(newsType, currentPage); mAdapter.setDatas(newsItems); isLoadingDataFromNetWork = true; // 设置刷新时间 AppUtil.setRefreashTime(getActivity(), newsType); // 清除数据库数据 mNewsItemDao.deleteAll(newsType); // 存入数据库 mNewsItemDao.add(newsItems); } catch (CommonException e) { e.printStackTrace(); isLoadingDataFromNetWork = false; return TIP_ERROR_SERVER; } } else { isConnNet = false; isLoadingDataFromNetWork = false; // TODO从数据库中加载 List<NewsItem> newsItems = mNewsItemDao.list(newsType, currentPage); mDatas = newsItems; //mAdapter.setDatas(newsItems); return TIP_ERROR_NO_NETWORK; } return -1; }
首先检查网络连接情况,没有的话,则去数据库加载,并设置isLoadingDataFromNetWork=false,如果有的话从网络加载,并清空该类型新闻的数据,更新数据库缓存数据。
下面是完整MainFragment.java:
package com.zhy.csdndemo; import java.util.ArrayList; import java.util.List; import me.maxwin.view.IXListViewLoadMore; import me.maxwin.view.IXListViewRefreshListener; import me.maxwin.view.XListView; import android.annotation.SuppressLint; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.zhy.bean.CommonException; import com.zhy.bean.NewsItem; import com.zhy.biz.NewsItemBiz; import com.zhy.csdn.Constaint; import com.zhy.csdndemo.adapter.NewsItemAdapter; import com.zhy.csdndemo.dao.NewsItemDao; import com.zhy.csdndemo.util.AppUtil; import com.zhy.csdndemo.util.Logger; import com.zhy.csdndemo.util.NetUtil; import com.zhy.csdndemo.util.ToastUtil; @SuppressLint("ValidFragment") public class MainFragment extends Fragment implements IXListViewRefreshListener, IXListViewLoadMore { private static final int LOAD_MORE = 0x110; private static final int LOAD_REFREASH = 0x111; private static final int TIP_ERROR_NO_NETWORK = 0X112; private static final int TIP_ERROR_SERVER = 0X113; /** * 是否是第一次进入 */ private boolean isFirstIn = true; /** * 是否连接网络 */ private boolean isConnNet = false; /** * 当前数据是否是从网络中获取的 */ private boolean isLoadingDataFromNetWork; /** * 默认的newType */ private int newsType = Constaint.NEWS_TYPE_YEJIE; /** * 当前页面 */ private int currentPage = 1; /** * 处理新闻的业务类 */ private NewsItemBiz mNewsItemBiz; /** * 与数据库交互 */ private NewsItemDao mNewsItemDao; /** * 扩展的ListView */ private XListView mXListView; /** * 数据适配器 */ private NewsItemAdapter mAdapter; /** * 数据 */ private List<NewsItem> mDatas = new ArrayList<NewsItem>(); /** * 获得newType * * @param newsType */ public MainFragment(int newsType) { this.newsType = newsType; Logger.e(newsType + "newsType"); mNewsItemBiz = new NewsItemBiz(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.tab_item_fragment_main, null); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mNewsItemDao = new NewsItemDao(getActivity()); mAdapter = new NewsItemAdapter(getActivity(), mDatas); /** * 初始化 */ mXListView = (XListView) getView().findViewById(R.id.id_xlistView); mXListView.setAdapter(mAdapter); mXListView.setPullRefreshEnable(this); mXListView.setPullLoadEnable(this); mXListView.setRefreshTime(AppUtil.getRefreashTime(getActivity(), newsType)); // mXListView.NotRefreshAtBegin(); if (isFirstIn) { /** * 进来时直接刷新 */ mXListView.startRefresh(); isFirstIn = false; }else { mXListView.NotRefreshAtBegin(); } } @Override public void onRefresh() { new LoadDatasTask().execute(LOAD_REFREASH); } @Override public void onLoadMore() { new LoadDatasTask().execute(LOAD_MORE); } /** * 记载数据的异步任务 * * @author zhy * */ class LoadDatasTask extends AsyncTask<Integer, Void, Integer> { @Override protected Integer doInBackground(Integer... params) { switch (params[0]) { case LOAD_MORE: loadMoreData(); break; case LOAD_REFREASH: return refreashData(); } return -1; } @Override protected void onPostExecute(Integer result) { switch (result) { case TIP_ERROR_NO_NETWORK: ToastUtil.toast(getActivity(), "没有网络连接!"); mAdapter.setDatas(mDatas); mAdapter.notifyDataSetChanged(); break; case TIP_ERROR_SERVER: ToastUtil.toast(getActivity(), "服务器错误!"); break; default: break; } mXListView.setRefreshTime(AppUtil.getRefreashTime(getActivity(), newsType)); mXListView.stopRefresh(); mXListView.stopLoadMore(); } } /** * 下拉刷新数据 */ public Integer refreashData() { if (NetUtil.checkNet(getActivity())) { isConnNet = true; // 获取最新数据 try { List<NewsItem> newsItems = mNewsItemBiz.getNewsItems(newsType, currentPage); mAdapter.setDatas(newsItems); isLoadingDataFromNetWork = true; // 设置刷新时间 AppUtil.setRefreashTime(getActivity(), newsType); // 清除数据库数据 mNewsItemDao.deleteAll(newsType); // 存入数据库 mNewsItemDao.add(newsItems); } catch (CommonException e) { e.printStackTrace(); isLoadingDataFromNetWork = false; return TIP_ERROR_SERVER; } } else { isConnNet = false; isLoadingDataFromNetWork = false; // TODO从数据库中加载 List<NewsItem> newsItems = mNewsItemDao.list(newsType, currentPage); mDatas = newsItems; //mAdapter.setDatas(newsItems); return TIP_ERROR_NO_NETWORK; } return -1; } /** * 会根据当前网络情况,判断是从数据库加载还是从网络继续获取 */ public void loadMoreData() { // 当前数据是从网络获取的 if (isLoadingDataFromNetWork) { currentPage += 1; try { List<NewsItem> newsItems = mNewsItemBiz.getNewsItems(newsType, currentPage); mNewsItemDao.add(newsItems); mAdapter.addAll(newsItems); } catch (CommonException e) { e.printStackTrace(); } } else // 从数据库加载的 { currentPage += 1; List<NewsItem> newsItems = mNewsItemDao.list(newsType, currentPage); mAdapter.addAll(newsItems); } } }
接下来看看数据库的实现:
首先肯定是个Helper,没什么好说的。
package com.zhy.csdndemo.dao; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "csdn_app_demo"; public DBHelper(Context context) { super(context, DB_NAME, null, 1); } @Override public void onCreate(SQLiteDatabase db) { /** * id,title,link,date,imgLink,content,newstype */ String sql = "create table tb_newsItem( _id integer primary key autoincrement , " + " title text , link text , date text , imgLink text , content text , newstype integer );"; db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }
然后是我们的Dao:
package com.zhy.csdndemo.dao; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.zhy.bean.NewsItem; import com.zhy.csdndemo.util.Logger; public class NewsItemDao { private DBHelper dbHelper; public NewsItemDao(Context context) { dbHelper = new DBHelper(context); } public void add(NewsItem newsItem) { Logger.e("add news newstype " + newsItem.getNewsType()); String sql = "insert into tb_newsItem (title,link,date,imgLink,content,newstype) values(?,?,?,?,?,?) ;"; SQLiteDatabase db = dbHelper.getWritableDatabase(); db.execSQL(sql, new Object[] { newsItem.getTitle(), newsItem.getLink(), newsItem.getDate(), newsItem.getImgLink(), newsItem.getContent(), newsItem.getNewsType() }); db.close(); } public void deleteAll(int newsType) { String sql = "delete from tb_newsItem where newstype = ?"; SQLiteDatabase db = dbHelper.getWritableDatabase(); db.execSQL(sql, new Object[] { newsType }); db.close(); } public void add(List<NewsItem> newsItems) { for (NewsItem newsItem : newsItems) { add(newsItem); } } /** * 根据newsType和currentPage从数据库中取数据 * * @param newsType * @param currentPage * @return */ public List<NewsItem> list(int newsType, int currentPage) { Logger.e(newsType + " newsType"); Logger.e(currentPage + " currentPage"); // 0 -9 , 10 - 19 , List<NewsItem> newsItems = new ArrayList<NewsItem>(); try { int offset = 10 * (currentPage - 1); String sql = "select title,link,date,imgLink,content,newstype from tb_newsItem where newstype = ? limit ?,? "; SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor c = db.rawQuery(sql, new String[] { newsType + "", offset + "", "" + (offset + 10) }); NewsItem newsItem = null; while (c.moveToNext()) { newsItem = new NewsItem(); String title = c.getString(0); String link = c.getString(1); String date = c.getString(2); String imgLink = c.getString(3); String content = c.getString(4); Integer newstype = c.getInt(5); newsItem.setTitle(title); newsItem.setLink(link); newsItem.setImgLink(imgLink); newsItem.setDate(date); newsItem.setNewsType(newstype); newsItem.setContent(content); newsItems.add(newsItem); } c.close(); db.close(); Logger.e(newsItems.size() + " newsItems.size()"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return newsItems; } }
提供了增加单条记录,多条记录,根据类型删除记录等方法。
最后把网络的辅助类也贴出来:
package com.zhy.csdndemo.util; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; /** * 判断当前手机联网的渠道 * * @author Administrator * */ public class NetUtil { /** * 检查当前手机网络 * * @param context * @return */ public static boolean checkNet(Context context) { // 判断连接方式 boolean wifiConnected = isWIFIConnected(context); boolean mobileConnected = isMOBILEConnected(context); if (wifiConnected == false && mobileConnected == false) { // 如果都没有连接返回false,提示用户当前没有网络 return false; } return true; } // 判断手机使用是wifi还是mobile /** * 判断手机是否采用wifi连接 */ public static boolean isWIFIConnected(Context context) { // Context.CONNECTIVITY_SERVICE). ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); if (networkInfo != null && networkInfo.isConnected()) { return true; } return false; } public static boolean isMOBILEConnected(Context context) { ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); if (networkInfo != null && networkInfo.isConnected()) { return true; } return false; } }
今天到此结束,现在基本就剩下,文章的详细信息的展示,和对页面上的图片进行保存了。
如果这篇文章对你有用,可以顶一个~
源码点击此处下载