基于Android原生开发的理财小助手APP
一、實驗題目
????個人理財小助手
二、實驗目的
三、總體設計
(含背景知識或基本原理與算法、或模塊介紹、設計步驟等)
3.1背景知識
???????基于android的理財小助手app,開發采用了增量式軟件開發模型。主要應用了listView、button、editText、textView、spinner、dialog、CalendarView、menu等Android原生控件,以及自定義View控件ShanView(扇形圖)、CircleProgressBar(環形進度條);采用了分層式類似MVC的結構,分為Activity(View)、JavaBean(Model)、Service(Control),另外有Util包(工具類,包含字符串處理類、時間格式轉換類、數據庫操作類等)。以達到在模塊層次上減小耦合、提高內聚的設計目標。
3.2 總體設計
3.3模塊介紹
3.31登錄注冊模塊
(1)登錄模塊:主要是用戶登錄功能的實現,具有填寫用戶名、密碼、選擇角色(用戶/管理員)的表單。還有登錄的跳轉按鈕。登錄方面,密碼填寫為密碼框,并附帶一個圖標按鈕(isSelected實現)可以點擊實現顯示/隱藏密碼。非初次登錄,當用戶填寫完用戶名后,會自動填寫密碼(sharedpreferences實現)。當用戶名文本框焦點改變時,上方的圓形頭像會自動旋轉一周(animation實現)。涉及到數據庫用戶表的查詢操作,語句為"select password from user where name =’" + name + “’”;頁面圖片為圖1。
(2)注冊模塊:主要是用戶注冊功能的實現。Ui界面用的是登錄模塊的,具有判斷用戶是否已經被注冊的功能。用戶名和密碼不為空。涉及到數據庫用戶表的查詢插入操作。管理員方面,會自動創建一個管理員賬號,sql語句為"insert into user (name,password,role) values (‘admin’,‘admin’,‘管理員’)";頁面圖片為圖1。
3.32數據展示模塊
(1)季節收入展示模塊:利用circleprogressbar(環形進度條)實現分季節統計收入金額。共分春夏秋冬四個季節,春季(3、4、5月)、夏季(6、7、8月)、秋季(9、10、11月)、冬季(12、1、2月)。頁面圖片為圖6。
(2)季節支出展示模塊:與季節收入展示模塊類似,利用circleprogressbar(環形進度條)實現分季節統計收入金額。共分春夏秋冬四個季節,春季(3、4、5月)、夏季(6、7、8月)、秋季(9、10、11月)、冬季(12、1、2月)。頁面圖片為5。
(3)本月收入展示模塊:獲取當前月份,分類(外快、兼職、工資、津貼)統計收入來源,使用自定義扇形圖控件shanView,涉及到數據庫的語句為"select sum(income.money) as money from income where name =’"+ LoginActivity.name +"’ and date like ‘%"+year+"-"+month+"-%’",思路是先分月求和查詢,然后再求季節總和。頁面圖片為圖11。
(4)本月支出展示模塊:與本月收入展示模塊類似,獲取當前月份,分類(餐飲、交通、娛樂、購物)統計支出方向,使用自定義扇形圖控件shanView,涉及到數據庫的語句為"select sum(outcome.money) as money from outcome where name =’"+ LoginActivity.name +"’ and date like’%"+year+"-"+month+"-%’",思路也是先分月求和查詢,然后再求季節總和。頁面圖片為圖11。
3.33數據管理模塊
便簽管理模塊:分兩個頁面,一個新增便簽,一個查詢便簽。其中新增便簽較為簡單,查詢便簽是按照便簽內容進行模糊查詢。運用數據庫查詢語句關鍵字like。例如select * from tips where info like ‘%今天%’;通過檢測文本框的內容是否發生變化,如發生變化,則執行一次模糊查詢并把結果顯示在下方的文本框中。頁面圖片為圖10和圖12。
收支管理模塊:由新增收支記錄、刪除收支記錄、統計收支(3.32 數據展示模塊)、查詢收支記錄組成。新增收支比較簡單,查詢和刪除寫在了一起,具體實現思路是查詢所有的記錄,然后用lisetview展示,利用setOnItemClickListener()監聽實現對行(記錄)的選中,然后彈出一個對話框,可以選擇是否刪除此條記錄。頁面圖片為圖3。
具體代碼如下
dialog = new AlertDialog.Builder(MyIncomeActivity.this).setTitle("系統提示").setMessage("是否刪除此條記錄?").setIcon(R.mipmap.ic_launcher).setPositiveButton("確定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 刪除一條記錄String sql = "delete from income where _id="+id_selected;System.out.println(sql);dbprocess2.execSql(sql); Toast.makeText(MyIncomeActivity.this,"刪除成功,請刷新頁面查看",Toast.LENGTH_SHORT).show();}}) .setNegativeButton("取消",null).create();數據導出模塊:導出數據為txt文件,雖然有些過時,沒有采取新功能比如發郵件的形式,但是也算是做了經典的文件存儲功能的實現,鞏固了基礎。思路是查詢所有記錄,存入arraylist中(數組隊列),然后在文件輸出流中用getXX()方法取出來,存入文件。
具體實現代碼如下
3.34系統設置模塊
系統設置模塊主要由修改密碼、修改壁紙組成。都比較簡單,這里就不一一贅述了。長話短說,修改壁紙主要是利用sharepreferences來存儲當前壁紙,然后主菜單一調用onCreate()方法就會設置壁紙。
四、詳細設計(含主要的數據結構、程序流程圖、關鍵代碼等)
4.1數據庫設計
4.11實體設計:E-R圖
實體類:用戶、收入表、支出表、收支便簽
4.12Sql語句:
CREATE TABLE income(_id integer primary key autoincrement,name varchar(20) not null,money varchar(20) not null,date varchar(20) not null,class varchar(20) not null,payer varchar(20) not null,comment varchar(50) not null);CREATE TABLE outcome(_id integer primary key autoincrement,name varchar(20) not null,money varchar(20) not null,date varchar(20) not null,class varchar(20) not null,location varchar(20) not null,comment varchar(50) not null);CREATE TABLE tips(_id integer primary key autoincrement,name varchar(20) not null,info varchar(50) not null);CREATE TABLE user(name varchar(20) primary key not null,password varchar(20) not null,role varchar(20) not null);4.2活動圖設計
4.3用例圖設計
4.4關鍵代碼
4.41數據庫部分:
package com.example.myapplication5.Utils; /* 本來想定義為靜態工具類的,由于有傳入參數helper,故不這樣設置 */ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast;import static java.lang.Integer.parseInt;public class dbProcess2 {// 啟動類private MyHelper helper;// 數據庫private SQLiteDatabase db;public dbProcess2(MyHelper helper) {this.helper = helper;}// 每次的數據庫對象要重新獲取 // 增刪改public void execSql(String sql) {// 獲取數據庫db = helper.getWritableDatabase();db.execSQL(sql);db.close();}// 查詢收支記錄public void query(String sql, TextView mTvShow, Context context) {// 獲取數據庫db = helper.getWritableDatabase();Cursor cursor = db.rawQuery(sql, null);int number = cursor.getCount();if (cursor.getCount() == 0) {mTvShow.setText("");Toast.makeText(context, "沒有數據", Toast.LENGTH_SHORT).show();} else {cursor.moveToFirst(); // 下標從0開始mTvShow.append("\n------------------------------");mTvShow.setText("\n" + cursor.getString(2) + "元," + cursor.getString(3) + "," + cursor.getString(4) + "," + cursor.getString(5) + "," + cursor.getString(6));mTvShow.append("\n------------------------------");}while (cursor.moveToNext()) {mTvShow.append("\n" + cursor.getString(2) + "元," + cursor.getString(3) + "," + cursor.getString(4) + "," + cursor.getString(5) + "," + cursor.getString(6) );mTvShow.append("\n------------------------------");}cursor.close();db.close();}// 查詢收支便簽public void queryTips(String sql, TextView mTvShow, Context context) {// 獲取數據庫db = helper.getWritableDatabase();Cursor cursor = db.rawQuery(sql, null);int number = cursor.getCount();System.out.println(number+"------");if (cursor.getCount() == 0) {mTvShow.setText("");System.out.println(1111);Toast.makeText(context, "沒有數據", Toast.LENGTH_SHORT).show();} else {Toast.makeText(context,"查詢到"+number+"條數據",Toast.LENGTH_SHORT).show();cursor.moveToFirst(); // 下標從0開始 // setText-->appendSystem.out.println(cursor.getString(0)+cursor.getString(2));mTvShow.setText(cursor.getString(0) + "," + cursor.getString(2) + ";");}while (cursor.moveToNext()) {System.out.println(cursor.getString(0)+cursor.getString(2));mTvShow.append("\n" + cursor.getString(0) + "," + cursor.getString(2) + ";");}cursor.close();db.close();}// 根據用戶名查詢密碼或權限public String queryOne(String sql) {// 獲取數據庫db = helper.getWritableDatabase();Cursor cursor = db.rawQuery(sql, null);if (cursor.getCount() == 0) {return "用戶不存在";} else {cursor.moveToFirst();/* 這里index為何是0 解答:因為這里獲取的是單個列---select password/role */return cursor.getString(0);}}// 根據用戶名查詢收入/支出表 根據月份查詢收支表public int queryMoney(String sql) {int count = 0;// 獲取數據庫db = helper.getWritableDatabase();Cursor cursor = db.rawQuery(sql, null);System.out.println("查詢到的記錄條數"+cursor.getCount());if (cursor.getCount() == 0) {return 0;} else {cursor.moveToFirst();String num = cursor.getString(0);if (StringUtils.isBlank(num)){ // 這里需要加個判斷是否為空,為啥總會查到一條記錄 ???return 0;}count = parseInt(num);System.out.println("-----" + num + "-----");}cursor.close();db.close();return count;}}4.5 運行效果截圖
圖1 登錄注冊
圖2 后臺管理頁
圖3 我的收入頁
圖4 數據管理頁
圖5-6 數據可視化頁面
圖7 主菜單界面
圖8 新增收入頁
圖9 系統設置頁
圖10 新增便簽頁
圖11 本月收入/支出
圖12 查詢便簽
五、實驗結果與分析
???????本次課程設計實現了登錄注冊、新增收入、新增支出、查詢所有收入、查詢所有支出、按id刪除收入記錄、按id刪除支出記錄、統計當年季節收入金額及比例并展示、統計當年季節支出金額及比例并展示、統計當月收入來源、統計當月支出去向(扇形圖)、更換壁紙、更改密碼、數據導出(txt文件)新增收支便簽、查詢收支便簽(按內容進行模糊查詢like)等功能。總體上達到了指導書上的設計要求。并有些許創新,比如在控件的使用上選擇了更多沒接觸過的控件,如在收支記錄的時間選擇上使用了CalendarView、在收支類別上選擇了Spinner、在數據管理頁功能選擇上使用了menu、在季節收支比例上使用了自定義環形進度條,并加入了動態繪圖功能,豐富了用戶體驗。還有學習借鑒了csdn上大佬的自定義扇形圖控件。
六、小結與心得體會
???????本次課程設計歷時兩周,感受頗多,收獲頗多。可以算是自己獨立設計的比較成熟的第一個項目吧,應用了數據庫技術、mvc架構思想、分層分級思想、android界面設計、組件設計。這個項目代碼量比較大,有三十多個類,所以代碼冗余也是一大缺點,有些功能函數其實可以分離出去單獨成一個類,但是分離之后的接口設計層次我又有點不知所措。比如自己封裝好的數據庫操作類dbprocess2.class,在增刪改查上實現了通用的功能,但是在某些頁面上查詢展示需要個性化需求,又不得不重寫一個類似的方法,不然為了通用又得改原方法。這個涉及到個人在內聚耦合的選擇。我盡量去做到“低耦合,高內聚”
???????代碼設計中我盡量秉持著規范化原則,每個模塊都寫了注釋,不僅方便別人看懂,也能然自己思路清晰,方便查找修改bug。在設計中我也使用了測試類junit,這樣尤其對于android這樣需要頁面驅動的方法調用比較好單獨測試一個模塊一個函數的功能,經測試后再加入原程序。
???????在題目選擇方面,相比ui設計,我更注重業務邏輯,所以選擇了界面較為簡單的理財小助手。其他題目的ui設計較為復雜,再去開發完整會比較耗時。但也會適當加入美化頁面的新控件,以使自己在熟練掌握已學知識的基礎上進行拓展。立足基礎,增量式設計。
???????本次課程設計由自己獨立完成,做出成品的那一刻覺得所有辛苦都值得了,滿滿的成就感,每個作品就像自己的孩子一樣,都記錄著自己成長的足跡。
???????也感謝老師在最后的驗收環節給予我的意見和建議以及肯定,我會盡量去改正。比如流程圖的設計上我會更加規范化,采用工程化的uml設計,規范自己。盡量養成好的習慣,這次課程設計的過程中我做了大量的記錄工作,每天都有簡潔的寫日志和總結自己遇到的問題,然后多思考大體確定第二天的設計目標,要加哪些模塊等等。在這樣也使我目標明確,有方向感。在敲代碼的過程中,并不顯得輕松,但我還算比較有韌性,遇到難題不輕易放棄,盡量去學習別人的經驗,搜索了大量的博客,有些人寫的比較好我采納了。這樣才使得最后能夠做出來。
總結
以上是生活随笔為你收集整理的基于Android原生开发的理财小助手APP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 估值报告写作第一讲——第五届CVA估值建
- 下一篇: 教你如何加入一家好的广告联盟——如微博0