• 实现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;
    	}
    }
    

    今天到此结束,现在基本就剩下,文章的详细信息的展示,和对页面上的图片进行保存了。


    如果这篇文章对你有用,可以顶一个~


    源码点击此处下载




  • 相关阅读:
    读《梦断代码》有感
    The Third Group Meeting!
    第一次课程作业项目报告
    第四次读后感
    个人作业进度(五)
    个人作业进度(四)
    个人作业进度(三)
    个人进度(二)
    个人作业进度(一)
    java中类的封装与继承
  • 原文地址:https://www.cnblogs.com/oversea201405/p/3752037.html
Copyright © 2020-2023  润新知