通过网上公开的数据进行汇率查询,这里用到了jsoup的包,详细可以参考另外一篇我的文章​​《jSoup Cookbook-提取数据 7 使用选择器语法查找元素》​​ 下面附上代码rate.java 这个是数据结构类,无需更多的解释

package com.nbcio.baishicha.rate;
import java.io.Serializable;
public class Rate implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String title;
private String name;
private String english;
private String xhbuy;//现汇买入价
private String xcbuy;//现钞买入价
private String sell;//卖出价
private String picurl;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setEnglish(String english) {
this.english = english;
}
public String getEnglish() {
return english;
}
public void setSell(String sell) {
this.sell = sell;
}
public String getSell() {
return sell;
}
public void setXcbuy(String xcbuy) {
this.xcbuy = xcbuy;
}
public String getXcbuy() {
return xcbuy;
}
public void setXhbuy(String xhbuy) {
this.xhbuy = xhbuy;
}
public String getXhbuy() {
return xhbuy;
}
public void setPicurl(String picurl) {
this.picurl = picurl;
}
public String getPicurl() {
return picurl;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

主界面是个简单的listview,这里用到了异步调用与一个ArrayAdapter的适配器

package com.nbcio.baishicha.rate;
import java.util.ArrayList;
import com.nbcio.baishicha.R;
import android.app.ListActivity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
public class RateList extends ListActivity {
protected final static int MENU_DELETE = Menu.FIRST;
protected final static int MENU_DEMO = Menu.FIRST + 1;
public final static String SER_KEY = "com.nbcio.baishicha.rate";
ArrayList<Rate> alrate = new ArrayList<Rate>();
private RateAdapter listAdapter;
View viewProgressBar;
RateData api = new RateData();
TextView title;
Button btreturn,btrefresh;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ratelist);
viewProgressBar = findViewById(R.id.rateProgress);
//Bundle extras=getIntent().getExtras(); //getIntent()返回启动这个activity的intent
this.setTitle(getResources().getText(R.string.app_name) + "-" + "中国银行外汇牌价");
title = (TextView) findViewById(R.id.tvtitle);
btreturn = (Button)findViewById(R.id.btreturn);
btreturn.setSelected(true);
btreturn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
RateList.this.finish();
}
});
update();
}
void update() {
// 刷新msg的内容
try {
GetFundData uptask = new GetFundData();
uptask.execute();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class GetFundData extends AsyncTask<String, Integer, String> {
// 后面尖括号内分别是参数,进度(publishProgress用到),返回值 类型
protected String doInBackground(String... code) {
// TODO Auto-generated method stub
try {
String str = api.getAllRate();
alrate = (ArrayList<Rate>) api.ReadRateHtml(str);
} catch (Exception e) {
e.printStackTrace();
return "error";
}
return "ok";//返回大写的OK好像有问题,不知道为什么?
}
protected void onProgressUpdate(Integer... progress) {
// tv.setText(String.valueOf(progress[0]));
// 这个函数在doInBackground调用publishProgress时触发,虽然调用时只有一个参数
// 但是这里取到的是一个数组,所以要用progesss[0]来取值
// 第n个参数就用progress[n]来取值
}
protected void onPostExecute(String result) {
// 生成动态数组,加入数据
String temp = "ok";
if ((alrate == null) (alrate.size() == 0)) {
Toast.makeText(RateList.this, "读取信息出错!",
Toast.LENGTH_LONG).show();
viewProgressBar.setVisibility(View.GONE);
return;
}
if (result.compareTo(temp) == 0) {
title.setText(alrate.get(0).getTitle());
viewProgressBar.setVisibility(View.GONE);
// 添加点击
RateList.this.setListAdapter(getAdapter());
RateList.this.getListView().setOnItemClickListener(
new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0,
View v, int position, long id) {
RateList.this.getAdapter().setSelectItem(position);
RateList.this.getAdapter().notifyDataSetInvalidated();
Intent intent = new Intent(RateList.this,
RateDetail.class);
Bundle mBundle = new Bundle();
mBundle.putSerializable(SER_KEY, alrate
.get(position));
intent.putExtras(mBundle);
startActivity(intent);
}
});
}
// doInBackground返回时触发,换句话说,就是doInBackground执行完后触发
// 这里的result就是上面doInBackground执行后的返回值,所以这里是"执行完毕"
}
}
private RateAdapter getAdapter(){
if(this.listAdapter==null){
listAdapter=new RateAdapter(this, alrate);
}
return listAdapter;
}
}

RateAdapter 从ArrayAdapter继承过来,这里因为数据也不大,所以就简单用了这个,但对数据大的时候这个效率比较低

package com.nbcio.baishicha.rate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.nbcio.baishicha.R;
import android.app.Activity;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class RateAdapter extends ArrayAdapter<Rate> {
int selectItem=-1;
public RateAdapter(Activity activity,
List<Rate> rateList) {
super(activity, 0, rateList);
}
private Map<Integer, View> viewMap = new HashMap<Integer, View>();
public void setSelectItem(int selectItem) {
this.selectItem = selectItem;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = this.viewMap.get(position);
if (rowView == null) {
LayoutInflater inflater = ((Activity) this.getContext())
.getLayoutInflater();
rowView = inflater.inflate(R.layout.raterow, null);
Rate rateBean = this.getItem(position);
if (rateBean != null) {
TextView tvName = (TextView) rowView.findViewById(R.id.tvratename);
tvName.setTextColor(Color.BLACK);
tvName.setText(rateBean.getName());
TextView tvXhbuy = (TextView) rowView.findViewById(R.id.tvxhbuy);
tvXhbuy.setTextColor(Color.BLACK);
tvXhbuy.setText(rateBean.getXhbuy());
TextView tvXcbuy = (TextView) rowView.findViewById(R.id.tvxcbuy);
tvXcbuy.setTextColor(Color.BLACK);
tvXcbuy.setText(rateBean.getXcbuy());
TextView tvSell = (TextView) rowView.findViewById(R.id.tvsell);
tvSell.setTextColor(Color.BLACK);
tvSell.setText(rateBean.getSell());
}
viewMap.put(position, rowView);
}
if (position == selectItem) {
rowView.setBackgroundColor(Color.WHITE);
}
else {
rowView.setBackgroundColor(Color.TRANSPARENT);
}
return rowView;
}
}

下面就是重点介绍的RateData数据解析类
根据返回的HTML页面通过jsoup进行解析过滤 

package com.nbcio.baishicha.rate;
import java.util.ArrayList;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.nbcio.baishicha.common.SysUtil;
/**
* 汇率查询类
* 主要从相应汇率网站获得数据
*
* @author lvqiyong
*/
public class RateData {
private static final String WAIHUI = "https://www.usd-cny.com/";
private static final String CHARTURL = "https://qq.ip138.com/hl.asp?from=";
/**
* 获取所有实时汇率列表内容的HTML数据
*
* @return String
* @throws Exception
* @author lvqiyong
*/
public String getAllRate()
throws Exception {
return new String(SysUtil.getRequest(WAIHUI, "gb2312"));
}
/**
* 获取查询的汇率趋势图的html数据
*
* @return String
* @throws Exception
* @author lvqiyong
*/
public String getRateChart(String key)
throws Exception {
return new String(SysUtil.getRequest(CHARTURL + key + "&to=CNY&q=100", "utf-8"));
}
/**
* 通过读取onlinecha的html数据,根据信息写到ArrayList<Rate>中
* @param String
* @return ArrayList<Rate>
* @throws Exception
* @author lvqiyong
*/
ArrayList<Rate> ReadRateHtml(String html) {
ArrayList<Rate> alrate = new ArrayList<Rate>();
try {
Document dom = Jsoup.parse(html);
Elements titleNode = dom.select("h1.top");
String title = titleNode.text();
title = title + dom.select("span.STYLE1").text();
title = title.replace("中国银行外汇牌价", "");
title = title.replace("工商银行汇率", "");
title = title.replace("实时汇率表", "");
Elements root = dom.select("TABLE[BORDERCOLOR]").select("tr");
int j = 0;
for (Element element : root) {
if (j==0) {
j++;
continue;
}
Elements rateNode = element.select("td");
int i = 0;
Rate rate = new Rate();
for (Element items : rateNode) {
switch (i) {
case 0:
Elements numNode = items.select("a");
String name = numNode.text();
int start = name.indexOf(" ") + 1;
rate.setName(name);
rate.setEnglish(name.substring(start).trim());
break;
case 1:
String tmp = "";
tmp = items.text();
tmp = tmp.replace(" ", "");
rate.setXhbuy(tmp);
break;
case 2:
String xctmp = "";
xctmp = items.text();
xctmp = xctmp.replace(" ", "");
rate.setXcbuy(xctmp);
break;
case 3:
String selltmp = "";
selltmp = items.text();
selltmp = selltmp.replace(" ", "");
rate.setSell(selltmp);
break;
default:
break;
}
i++;
}
rate.setTitle(title);
alrate.add(rate);
j++;
}
} catch (Exception e) {
e.printStackTrace();
}
return alrate;
}
/**
* 通过读取趋势图数据,根据js信息写到String中
* @param String
* @return String
* @throws Exception
* @author lvqiyong
*/
String ReadRateChart(String html) {
String scharturl = "";
try {
Document dom = Jsoup.parse(html);
Elements root = dom.select("img");
scharturl = root.attr("src");
} catch (Exception e) {
e.printStackTrace();
}
return scharturl;
}
}