商业级项目——基金客户端的架构设计与开发(下)(附源码)
Posted 朱培
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了商业级项目——基金客户端的架构设计与开发(下)(附源码)相关的知识,希望对你有一定的参考价值。
#项目简介上一次的博文中详细分析了基金项目的整体架构和主界面的UI设计。今天分享地方是剩下的3个页面及相应功能的实现。
#个人中心
个人中心界面,最开始会跳转到一个登陆界面,用户可以通过选择“身份证、基金账户、护照、户口本“,然后输入相应的账号和密码进行登陆。在这个界面中,还具有相应的记住密码,忘记密码功能。不输入是不允许进入账户的,当正确输入相应的账号密码后,通过和后台服务器进行验证登陆,登陆进去之后是一个账户详情页,有持仓查询、盈亏查询、交易查询等功能,在持仓查询中hi有总资产,活期宝、今年收益的详细信息。在下面通过一个listview展示自己已买基金的名称、收益率、代号等信息。
#交易界面
在这个页面中,若用户未登录,则在该页面最上方会提示:您还未登录”同时在右上角会有一个登陆按钮,通过点击该按钮可跳转至登陆页面。在交易页面,有充值、快速提现、查询等操作。
private class MySpinnerAdapter extends BaseAdapter implements SpinnerAdapter { @Override public int getCount() { return mListData.size(); } @Override public Object getItem(int position) { return mListData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.my_simple_spinner_item_recharge, null); } TextView view = (TextView) convertView .findViewById(R.id.recharge_spinner_view); view.setText(mListData.get(position).getName()); if (mListData.get(position).getSupport_withhold() == 1) { view.setEnabled(true); } else { view.setEnabled(false); } return convertView; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.my_simple_spinner_dropdown_item_recharge, null); } CheckedTextView view = (CheckedTextView) convertView.findViewById(R.id.recharge_spinner_item); view.setText(mListData.get(position).getName()); if (mListData.get(position).getSupport_withhold() == 1) { view.setEnabled(true); view.setCompoundDrawablesWithIntrinsicBounds(null, null, getResources().getDrawable(R.drawable.icon_withhold), null); } else { view.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); view.setEnabled(false); } return convertView; } }
#帮助界面
最后一个节目就是一个帮助界面了,这里有消息中心、帮助、意见反馈、关于我们。当点击拨打客服电话后,会跳转到电话拨打界面。
/** * 获取帮助消息 */ private Handler getHelpsHandler = new Handler() { public void handleMessage(Message msg) { dismissProgressDialog(); switch (msg.what) { case BaseHandlerUI.TASK_NOTIFY_RETURN_DATA: if (msg.obj != null) { try { bean = (GetHelpsResultBean) msg.obj; if (bean.state.equals("0")) { mDatabaseAdapter.open_fund(); mDatabaseAdapter.deleteAllHelpsData(); List<TreeViewAdapter.TreeNode> treeNode = adapter.GetTreeNode(); treeNode.clear(); for (int i = 0; i < bean.list.size(); i++) { mDatabaseAdapter.insertHelpsData(bean.list.get(i).ask, bean.list.get(i).reply); TreeViewAdapter.TreeNode node = new TreeViewAdapter.TreeNode(); node.parent = bean.list.get(i).ask; for (int ii = 0; ii < 1; ii++) { node.childs.add(bean.list.get(i).reply); } treeNode.add(node); } adapter.UpdateTreeNode(treeNode); expandableList.setAdapter(adapter); mDatabaseAdapter.close_funds(); } } catch (Exception e) { e.printStackTrace(); } } else { } break; } } };
#异步任务类
我们都知道,在安卓的应用开发中,子线程是不能直接操作主线程的,所以,如果有耗时操作 又或者是密集操作,就只能放在子线程中去处理,但是,如果处理后的结果需要更改UI的显示内容,这时候,就只能使用handler或AsyncTask进行处理。
AsyncTask是一个异步任务类,可以很容易在子线程中处理耗时操作。里面包含三个泛型参数params、progress、result,分别表示:
1.params:在执行asynctack时需要传入的参数,可用于后台任务中使用。
2.progress:后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3.result:当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
一个简单的泛型类如下:
<span style="font-size:18px;">class DownloadTask extends AsyncTask<Void,Integer,Boolean>{}</span>
public HttpRequestAsyncTask(HttpRequestInfo request, TaskListener listener, Context context) { this.context = context; request.putParam("device_info", ConfigUtil.getImei(context)) .putParam("app_version", ConfigUtil.getVersionName(context)) .putParam("market", context.getString(R.string.channel_str)); mListener = listener; mRequest = request; } public HttpRequestAsyncTask(HttpRequestInfo request, TaskListenerWithState taskListenerWithState, Context context) { this.context = context; request.putParam("device_info", ConfigUtil.getImei(context)) .putParam("app_version", ConfigUtil.getVersionName(context)) .putParam("market", context.getString(R.string.channel_str)); mListenerWithState = taskListenerWithState; mRequest = request; } @Override protected HttpResponseInfo doInBackground(Void... params) { if (!ConfigUtil.isConnect(context)) { return new HttpResponseInfo(null, HttpTaskState.STATE_NO_NETWORK_CONNECT); } try { if (mRequest != null) { if (mRequest.getRequestID() == -2) { return new HttpResponseInfo( HttpManager.postHttpRequest(mRequest), HttpTaskState.STATE_OK); } return new HttpResponseInfo( HttpManager.postHttpsRequest(mRequest), HttpTaskState.STATE_OK); } } catch (SocketTimeoutException e) { e.printStackTrace(); return new HttpResponseInfo("{\\"result\\":\\"3\\"}", HttpTaskState.STATE_OK); } catch (UnknownHostException e) { e.printStackTrace(); return new HttpResponseInfo("{\\"result\\":\\"3\\"}", HttpTaskState.STATE_OK); } catch (Exception e) { e.printStackTrace(); return new HttpResponseInfo("{\\"result\\":\\"3\\"}", HttpTaskState.STATE_OK); } return null; }
#HTTP编程
Http编程有请求和响应,这里我们把对json数据年度解析放到这一部分来讲解:
/** * Http 请求 */ public class HttpRequestInfo { public static final String TAG = "HttpRequestInfo"; /* Http 请求的 URL */ private String requestUrl; private int requestID; private Map<String, String> requestParams; public HttpRequestInfo(String url) { this.setRequestUrl(url); requestParams = new HashMap<String, String>(); } public HttpRequestInfo(String url, Map<String, String> params) { this.setRequestUrl(url); this.setRequestParams(params); } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } public Map<String, String> getRequestParams() { return requestParams; } public void setRequestParams(Map<String, String> requestParams) { this.requestParams = requestParams; } public String getParamsStr() { String str = ""; if (requestParams != null) { for (Entry<String, String> entry : requestParams.entrySet()) { String key = entry.getKey(); String val = entry.getValue(); key = URLEncoder.encode(key); val = URLEncoder.encode(val); str += key + "=" + val + "&"; } } if (str.equals("")) { return null; } LogUtil.i(TAG, this.requestUrl + str); return str; } public HttpRequestInfo putParam(String key, String value) { this.requestParams.put(key, value); return this; } public int getRequestID() { return requestID; } public void setRequestID(int requestID) { this.requestID = requestID; } }对于响应:
/** * Http 响应 */ public class HttpResponseInfo { public enum HttpTaskState { STATE_OK, STATE_NO_NETWORK_CONNECT, STATE_TIME_OUT, STATE_UNKNOWN, } public HttpResponseInfo(String result, HttpTaskState state) { this.result = result; this.state = state; } private HttpTaskState state; private String result; public HttpTaskState getState() { return state; } public void setState(HttpTaskState state) { this.state = state; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } }
数据库是一个非常重要的知识点,这里主要是分享一个这个基金中的数据库,这个数据库是一个小型的轻量级的数据库,
SQLiteOpenHelper有onCreate()、onUpgrade()两个方法。
private static class DatabaseHelper extends SQLiteOpenHelper { public DatabaseHelper(Context context, String name, CursorFactory factory, int version) { super(context, DB_NAME, null, version); } @Override public void onCreate(SQLiteDatabase db) { //创建所有数据库表 db.execSQL(DB_CREATE_FUND); db.execSQL(DB_CREATE_FAV_FUND); db.execSQL(DB_CREATE_HELPS_INFO); db.execSQL(DB_CREATE_FUND_DETAIL); db.execSQL(DB_CREATE_MSG); } // 更新基金数据 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_FUND); db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE_FAV_FUND); db.execSQL("DROP TABLE IF EXISTS " + DB_CREATE_HELPS_INFO); db.execSQL("DROP TABLE IF EXISTS " + DB_CREATE_FUND_DETAIL); db.execSQL("DROP TABLE IF EXISTS " + DB_CREATE_MSG); onCreate(db); } }
当然了,仅仅通过一篇博文是不可逆完全完整的说完整个项目了,这里写的仅仅是冰山一角,更多的内容还是希望读者自己去发现并学到里面的精华部分!当然咯,我相信有一部分人读了也基本上没看懂我写的是什么,那么请下载源码看看,互相学习咯!
源码下载地址:http://download.csdn.net/detail/sdksdk0/9461193
以上是关于商业级项目——基金客户端的架构设计与开发(下)(附源码)的主要内容,如果未能解决你的问题,请参考以下文章
“云”端的语雀:用 JavaScript 全栈打造商业级应用