通过网上公开的数据进行汇率查询,这里用到了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; } }