`
jgsj
  • 浏览: 1028270 次
文章分类
社区版块
存档分类
最新评论

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

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


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


源码点击此处下载




分享到:
评论

相关推荐

    客户端上显示csdn上的各类别下的的文章列表 (制作csdn app 三)

    `XListView`是一个可滚动的列表视图,它支持下拉刷新和上拉加载更多功能,这对于一个显示大量文章列表的应用来说非常实用。用户可以轻松地加载更多的文章,而无需离开当前界面。 `CSDNDemo`很显然是这个项目的主...

    制作csdn app 四

    2. **XListView**:这可能是一个自定义的ListView,提供了下拉刷新和上拉加载更多等功能,常用于显示长列表数据。开发者经常使用这种组件来提高用户体验,使用户能够轻松地滚动浏览内容并获取新的数据。 3. **CSDN...

    CSDN app(完)

    2. **XListView**:这是一个扩展的ListView组件,通常用于实现无限滚动或者下拉刷新功能。ListView是Android中常用的数据展示控件,而XListView在原生的基础上增加了更多实用功能,比如加载更多数据时的动画效果,...

    基于android的网上商城

    商品的推荐、浏览,改写上拉刷新下拉加载加载商品信息,商品信息是通过Jsoup从网页上抓取,获得XML解析并封装成实体类,然后适配到adapter;当然用户也可以搜索感兴趣的商品和店铺,Jsoup发送post请求后得到用户搜索...

    Android代码-仿知乎日报App

    文章列表的展示与缓存 文章内容的展示 今日热闻界面的轮播控件 下拉刷新 文章浏览到底部时自动加载更多 标记已读文章 自动缓存文章 夜间模式 依赖的开源项目 Gson Android-Universal-Image-Loader android-async-...

    wordpress下拉刷新插件

    下拉刷新功能基于JavaScript和CSS3技术,通常由一个可交互的元素(如一个div或header)和一些监听用户手势的事件组成。当用户在页面顶部向下滑动时,这个元素会显示出来,并且随着用户的下拉动作而动画化。一旦达到...

    Android 毕业设计仿斗鱼 Flutter 设计(内附源码,下载即可)

    - 开播列表上拉加载、下拉刷新、返回顶部 - 列表图片缓存加载优化 - 渐进式头部动画 - 底部导航切换保存页面状态 - HTTP缓存、IO缓存 - 直播间webSocket消息弹幕、礼物 - 页面路由传值 - RxDart全局消息通信封装 - ...

    Android代码-一款进行安卓面试复习的APP

    提供业内动态新闻查看功能,数据爬取自CSDN,提供新闻缓存,方便随时查看。 每周会提供安卓开发周报,提供给用户最新的开发技术。 二、第三方引用 1、Swipelayout下拉刷新 2、Bmob移动云服务 3、Logger调试日志...

    基于Vue实现tab栏切换内容不断实时刷新数据功能

    本篇文章将详细介绍如何使用Vue来实现Tab栏切换时内容不断实时刷新数据的功能。 首先,理解产品需求:有多个Tab(例如5个),每个Tab对应不同的Ajax请求,内容区域相同,数据需要每3秒刷新一次。当用户切换Tab时,...

    下拉放大图片

    ListView本身是Android中用于显示可滚动列表的控件,而ParallaxListView则在其基础上增加了视差滚动的功能。它允许头部视图在用户下拉时以特定的比例放大,从而实现图片放大效果。 要实现这个功能,我们首先需要...

    Smartfirst去除了所有头布局只保留了基础样式得源码

    描述中的链接指向了一篇CSDN博客文章,虽然具体内容无法直接展示在这里,但我们可以推测该文章可能详细介绍了这个优化过程,包括为何要去除头布局、实现这一优化的方法、以及如何保持基础样式的完整性和一致性。...

    AndroidStudio实现天气预报小程序源码

    使用SwipeRefreshLayout实现下拉刷新功能。 3. 数据缓存:考虑使用本地存储(如SharedPreferences或SQLite)缓存最近的天气信息,提高应用响应速度。 4. 图标显示:根据天气情况显示相应的图标,可以使用Glide或...

    毕业设计_淘宝天猫优惠券.zip

    返回首页依次往下的是一个分类导航条,在这里可以查看热门的一些分类,所有的列表都是支持上拉刷新和下拉加载的。 依次往下是一个焦点图,焦点图的商品是由管理员在后台进行配置,当配置的商品优惠券被领完时 ,App...

    ListView优化Demo

    总结,ListView优化主要包括视图复用、适配器优化、ViewHolder模式、数据分页加载等,而`SwipeRefreshLayout`提供了便捷的下拉刷新功能。通过这些策略,我们可以使ListView在处理大数据量时仍保持流畅,提供更好的...

Global site tag (gtag.js) - Google Analytics