本文主要讲解实现了一个CSDN的安卓客户端,主要知识点如下

  1. java爬虫获取网页数据
  2. 将java程序打包成jar包
  3. Fragment+viewpager+TabPageIndicator实现Tab效果
  4. gestureImageView实现放大缩小图片
  5. imageLodar实现异步加载图上
  6. XListView实现下拉刷新

java爬虫获取网页资源

package com.zhy.biz;  

import java.util.ArrayList;
import java.util.List; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import com.zhy.bean.CommonException;
import com.zhy.bean.NewsItem;
import com.zhy.csdn.DataUtil;
import com.zhy.csdn.URLUtil; /**
* 处理NewItem的业务类
* @author zhy
*
*/
public class NewsItemBiz
{
/**
* 业界、移动、云计算
*
* @param htmlStr
* @return
* @throws CommonException
*/
public List<NewsItem> getNewsItems( int newsType , int currentPage) throws CommonException
{
String urlStr = URLUtil.generateUrl(newsType, currentPage); String htmlStr = DataUtil.doGet(urlStr); List<NewsItem> newsItems = new ArrayList<NewsItem>();
NewsItem newsItem = null; Document doc = Jsoup.parse(htmlStr);
Elements units = doc.getElementsByClass("unit");
for (int i = 0; i < units.size(); i++)
{
newsItem = new NewsItem();
newsItem.setNewsType(newsType); Element unit_ele = units.get(i); Element h1_ele = unit_ele.getElementsByTag("h1").get(0);
Element h1_a_ele = h1_ele.child(0);
String title = h1_a_ele.text();
String href = h1_a_ele.attr("href"); newsItem.setLink(href);
newsItem.setTitle(title); Element h4_ele = unit_ele.getElementsByTag("h4").get(0);
Element ago_ele = h4_ele.getElementsByClass("ago").get(0);
String date = ago_ele.text(); newsItem.setDate(date); Element dl_ele = unit_ele.getElementsByTag("dl").get(0);// dl
Element dt_ele = dl_ele.child(0);// dt
try
{// 可能没有图片
Element img_ele = dt_ele.child(0);
String imgLink = img_ele.child(0).attr("src");
newsItem.setImgLink(imgLink);
} catch (IndexOutOfBoundsException e)
{ }
Element content_ele = dl_ele.child(1);// dd
String content = content_ele.text();
newsItem.setContent(content);
newsItems.add(newsItem);
} return newsItems; } }

详细实现参见链接

抓取csdn上的各类别的文章 (制作csdn app 二) - Hongyang - 博客频道 - CSDN.NET

将java项目打包成jar包

参考链接:在Eclipse中将Java项目打包为jar - 闵开慧的个人页面 - 开源中国社区

Fragment+viewpager+TabPageIndicator实现Tab效果

package com.zhy.csdndemo;  

import com.viewpagerindicator.TabPageIndicator;  

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager; public class MainActivity extends FragmentActivity
{
private TabPageIndicator mIndicator ;
private ViewPager mViewPager ;
private FragmentPagerAdapter mAdapter ; @Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mIndicator = (TabPageIndicator) findViewById(R.id.id_indicator);
mViewPager = (ViewPager) findViewById(R.id.id_pager);
mAdapter = new TabAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mAdapter);
mIndicator.setViewPager(mViewPager, 0); } }

详细实现参见链接

Android 使用Fragment,ViewPagerIndicator 制作csdn app主要框架 - Hongyang - 博客频道 - CSDN.NET

viewPager的适配器

package com.zhy.csdndemo;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter; public class TabAdapter extends FragmentPagerAdapter
{ public static final String[] TITLES = new String[] { "业界", "移动", "研发", "程序员杂志", "云计算" }; public TabAdapter(FragmentManager fm)
{
super(fm);
} @Override
public Fragment getItem(int arg0)
{
MainFragment fragment = new MainFragment(arg0+1);
return fragment;
} @Override
public CharSequence getPageTitle(int position)
{
return TITLES[position % TITLES.length];
} @Override
public int getCount()
{
return TITLES.length;
} }

viewPager中的Fragment实现,其中用xListView实现了获取数据与刷新等功能

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; @SuppressLint("ValidFragment")
public class MainFragment extends Fragment implements IXListViewRefreshListener, IXListViewLoadMore
{
/**
* 默认的newType
*/
private int newsType = Constaint.NEWS_TYPE_YEJIE;
/**
* 当前页面
*/
private int currentPage = 1;
/**
* 处理新闻的业务类
*/
private NewsItemBiz mNewsItemBiz;
/**
* 扩展的ListView
*/
private XListView mXListView;
/**
* 数据适配器
*/
private NewsItemAdapter mAdapter; /**
* 数据
*/
private List<NewsItem> mDatas = new ArrayList<NewsItem>(); /**
* 获得newType
* @param newsType
*/
public MainFragment(int newsType)
{
this.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);
mAdapter = new NewsItemAdapter(getActivity(), mDatas);
/**
* 初始化
*/
mXListView = (XListView) getView().findViewById(R.id.id_xlistView);
mXListView.setAdapter(mAdapter);
mXListView.setPullRefreshEnable(this);
mXListView.setPullLoadEnable(this);
//mXListView.NotRefreshAtBegin();
/**
* 进来时直接刷新
*/
mXListView.startRefresh();
} @Override
public void onRefresh()
{
new LoadDatasTask().execute();
} @Override
public void onLoadMore()
{
// TODO Auto-generated method stub }
/**
* 记载数据的异步任务
* @author zhy
*
*/
class LoadDatasTask extends AsyncTask<Void, Void, Void>
{ @Override
protected Void doInBackground(Void... params)
{
try
{
List<NewsItem> newsItems = mNewsItemBiz.getNewsItems(newsType, currentPage);
mDatas = newsItems;
} catch (CommonException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} return null;
} @Override
protected void onPostExecute(Void result)
{
mAdapter.addAll(mDatas);
mAdapter.notifyDataSetChanged();
mXListView.stopRefresh();
} } }

xListView的adapter,其中使用了imageLoder

package com.zhy.csdndemo.adapter;

import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.zhy.bean.NewsItem;
import com.zhy.csdn.DataUtil;
import com.zhy.csdndemo.R; public class NewsItemAdapter extends BaseAdapter
{ private LayoutInflater mInflater;
private List<NewsItem> mDatas; /**
* 使用了github开源的ImageLoad进行了数据加载
*/
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions options; public NewsItemAdapter(Context context, List<NewsItem> datas)
{
this.mDatas = datas;
mInflater = LayoutInflater.from(context); imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder().showStubImage(R.drawable.images)
.showImageForEmptyUri(R.drawable.images).showImageOnFail(R.drawable.images).cacheInMemory()
.cacheOnDisc().displayer(new RoundedBitmapDisplayer(20)).displayer(new FadeInBitmapDisplayer(300))
.build();
} public void addAll(List<NewsItem> mDatas)
{
this.mDatas.addAll(mDatas);
} @Override
public int getCount()
{
return mDatas.size();
} @Override
public Object getItem(int position)
{
return mDatas.get(position);
} @Override
public long getItemId(int position)
{
return position;
} @Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if (convertView == null)
{
convertView = mInflater.inflate(R.layout.news_item_yidong, null);
holder = new ViewHolder(); holder.mContent = (TextView) convertView.findViewById(R.id.id_content);
holder.mTitle = (TextView) convertView.findViewById(R.id.id_title);
holder.mDate = (TextView) convertView.findViewById(R.id.id_date);
holder.mImg = (ImageView) convertView.findViewById(R.id.id_newsImg); convertView.setTag(holder);
} else
{
holder = (ViewHolder) convertView.getTag();
}
NewsItem newsItem = mDatas.get(position);
holder.mTitle.setText(DataUtil.ToDBC(newsItem.getTitle()));
holder.mContent.setText(newsItem.getContent());
holder.mDate.setText(newsItem.getDate());
if (newsItem.getImgLink() != null)
{
holder.mImg.setVisibility(View.VISIBLE);
imageLoader.displayImage(newsItem.getImgLink(), holder.mImg, options);
} else
{
holder.mImg.setVisibility(View.GONE);
} return convertView;
} private final class ViewHolder
{
TextView mTitle;
TextView mContent;
ImageView mImg;
TextView mDate;
} }

参考链接:

客户端上显示csdn上的各类别下的的文章列表 (制作csdn app 三) - Hongyang - 博客频道 - CSDN.NET

效果如下

CSDN客户端实现的更多相关文章

  1. 博客同步到CSDN客户端

    同步本人博客到CSDN客户端 http://blog.csdn.net/johnnyz1234

  2. [Tool] csdn客户端开发(非官方版)

    偶尔间看到一篇博客[清山博客]里讲述了他自己开发的一个CSDN博客客户端,并去下载体验了一下,然后就自己手痒也要开发一下 先看看结果图: 在文章列表里,鼠标右键可以操作[置顶.删除.评论权限]: 下面 ...

  3. 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23698511 今天继续对我们的csdn客户端未完成的功能进行实现,本篇博客接着客 ...

  4. Android 从网络中获取数据时 产生部分数据乱码的解决

    产生部分数据乱码的解决 标签: android部分中文乱码 2014-04-12 23:24 12366人阅读 评论(10) 收藏 举报 分类: [Android 基础](15) 版权声明:本文为博主 ...

  5. 掘金 Android 文章精选合集

    掘金 Android 文章精选合集 掘金官方 关注 2017.07.10 16:42* 字数 175276 阅读 50053评论 13喜欢 669 用两张图告诉你,为什么你的 App 会卡顿? - A ...

  6. Spring Authorization Server的使用

    Spring Authorization Server的使用 一.背景 二.前置知识 三.需求 四.核心代码编写 1.引入授权服务器依赖 2.创建授权服务器用户 3.创建授权服务器和客户端 五.测试 ...

  7. Redis C客户端API - God's blog - 博客频道 - CSDN.NET

    Redis C客户端API - God's blog - 博客频道 - CSDN.NET Redis安装步骤: 1.redis server安装 wget http://redis.googlecod ...

  8. CSDN Android客户端的制作 导航帖

    弄个导航贴,把相关知识来个汇总. CSDN Android的客户端的效果图: 分别通过以下博客进行详细的讲解: 1.Android 使用Fragment,ViewPagerIndicator 制作cs ...

  9. Android应用开发-小巫CSDN博客客户端开发开篇

    2014年9月8日 八月十五 祝各位中秋节快乐 小巫断断续续花了几个星期的时间开发了这么一款应用——小巫CSDN博客,属于私人定制的这样的一款应用,整个客户端的数据全部来自本人博客,是通过爬取本人博客 ...

随机推荐

  1. Linux下安装Nginx详细图解教程

    什么是Nginx? Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器,在高连接并发的情况下N ...

  2. C标准函数库(常用部分)

  3. iOS 代理与block 逆向传值 学习

    一般在项目中出现逆向传值的时候就需要用到代理.block 或者通知中心了.由于公司的项目底层封装的很好,所以项目做了三四个月就算碰到需要逆传的情况也不用自己处理.但是最近遇到了一个特别的情况就需要自己 ...

  4. pthread_rwlock

    读写锁   1.概述 读写锁与互斥量类似,不过读写锁允许更高的并行性.互斥量要么是锁住状态,要么是不加锁状态,而且一次只有一个线程对其加锁.读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不 ...

  5. DedeCms 5.x 本地文件包含漏洞(respond方法)

    漏洞版本: DedeCms 5.x 漏洞描述: DedeCms是免费的PHP网站内容管理系统. plus/carbuyaction.php里没有对变量进行严格的过滤 出现漏洞的两个文件为: Inclu ...

  6. GTP (GPRS隧道协议(GPRSTunnellingProtocol))

    GTP (GPRS隧道协议(GPRSTunnellingProtocol)) GTP (GPRS隧道协议(GPRSTunnellingProtocol)) 编辑 本词条缺少信息栏.名片图,补充相关内容 ...

  7. chown命令

    改变一个文件的所有者和组 1.命令格式: chown [选项]... [所有者][:[组]] 文件... 例子: komiles@iUbuntu:~/study/wordpress$ lltotal ...

  8. 建站时注意敏感词的添加_seo优化禁忌

    之前接手一个站点,网站标题中出现一个“三级医院”的词,虽然这个词在我们看来是没有问题的,医院评级中“三级医院”算是等级很高的,很多医院为了体现等级会在明显的地方着重加注.但是我们要考虑一下搜索引擎的分 ...

  9. WPF 路由事件总结

    1.什么是路由事件 已下为MSDN中的定义 功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对引发该事件的对象)调用处理程序的事件. 实现定义:路由事件是一个 CLR 事件,可以由 R ...

  10. 经典的SQL面试题

    SQL中 inner join. left join .right join. outer join之间的区别 A表(a1,b1,c1) B表(a2,b2) a1 b1 c1 a2 b2 01 数学 ...