20212408 2023-2024-2 《移动平台开发与实践》移动平台开发综合实践

20212408 2023-2024-2 《移动平台开发与实践》移动平台开发综合实践

一、实验目的

  • 灵活运用本学期所学习的知识,实现一个安卓APP的开发
  • 掌握Android应用开发的基础知识,包括Activity、SQLite数据库的使用和用户界面设计。
  • 了解SQLite数据库在Android应用中的集成与操作方法,学会创建、查询、更新和删除数据库记录。
  • 掌握Android Spinner和ListView控件的使用,通过下拉菜单和列表展示数据。
  • 学习实现收支记录的管理与查询功能,能够根据日期和类型筛选并显示对应的记录。 了解如何在Android应用中进行简单的计算操作,实现在指定条件下计算总金额。
  • 提升在移动平台上进行软件开发的综合能力,为后续复杂应用的开发打下基础。

二、实验内容

设计和实现一个记账本的 Android APP ,数据库采用 SQLite (也可以直接访问 Web 端 MySQL 数据库、或提供 Web
接口访问 MySQL 数据库)。能够完成用户注册、登录功能;进入记账本后可以录入收支记录,同时可以根据日期进行账单的查询。

三、实验要求

1.使用Java语言或者kotlin语言的基础知识,进一步加深对android的理解和掌握;搭建一个完整的安卓开发环境;
2.熟练运用安卓四大组件,完成一个安卓APP的开发与应用;
3.能够熟练使用数据库和网络上提供的API来实现复杂功能的调用。

四、APP设计及关键代码实现

(一)需求分析

能够实现用户注册和登录
可以对收入和支出进行管理(单条收支记录的添加、删除和修改,收入和支出每一条记录至少包括日期、类型、金额和说明。)
可以对收入和支出进行查询(根据时间段、类别等进行查询)
可以对收入和支出完成统计(例如某个月、某个星期或指定时间段的总收支)
在这里插入图片描述

(二)数据库设计

为了实现记账本的基本功能,我们需要对其需要存入的信息进行数据库的设计。
基本情况来说简单的只需要两个表即可。
首先是用户的信息表,设计为userinfo表,用于存储用户信息。用户表的基本内容为:ID 设计自增ID为主键即可;Uid 设置为用户名,upwd设置为用户密码。
其次是记账的信息记录,设计为record表,来存储账单信息。Record表的基本内容为:ID设置自增ID为主键,date为记账的日期,type为记账的类型,包括收入和支出,money设计为这笔记录的金额,state是这笔记录的备注或说明。
实现的场景比较简单,并没有太复杂的操作,所以使用两张对应表即可。但是还是有一些小问题不能很好解决。

关键代码实现
public class DBHelper extends SQLiteOpenHelper {
    public static final String DB_NAME = "Test.db";
    public static final String TABLE_NAME = "userinfo";
    public static final String COLUMN_USERID = "uid";
    public static final String COLUMN_USERPWD = "upwd";

DBHelper类继承自SQLiteOpenHelper,这是一个帮助类,用于管理数据库创建和版本管理。
DB_NAME是数据库名称,这里定义为"Test.db"。
TABLE_NAME是表名称,这里定义为"userinfo"。
COLUMN_USERID和COLUMN_USERPWD分别是表中存储用户ID和用户密码的列名称。

    public DBHelper(Context context) {
        super(context, DB_NAME, null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.execSQL(CREATE_TABLE);
            db.execSQL("insert into " + TABLE_NAME + " values('11','11')");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

DBHelper(Context context):构造方法用于初始化数据库。
super(context, DB_NAME, null, 1):调用父类SQLiteOpenHelper的构造方法,传递上下文、数据库名称和版本号。这里版本号设为1。
onCreate(SQLiteDatabase db):这个方法在数据库第一次创建时调用。
db.execSQL(CREATE_TABLE):执行创建表的SQL语句。
db.execSQL(“insert into " + TABLE_NAME + " values(‘11’,‘11’)”):插入初始数据,将用户ID和密码都设置为"11"。
try-catch块用于捕捉和处理可能的SQL异常。

(三)交互过程

设计完上面的基础内容后需要考虑各个activity之间是什么关系,如何操作才能正确实现跳转,需要对整体的框架进行搭建。
在这里插入图片描述

首先是用户登录界面,当我们输入正确的用户名和密码时,显示登录成功,并跳转至个人中心页面;当我们输入错误时,会提示登录失败,提示密码错误或者账号不存在;或者没有进行注册时,点击注册,这时会跳转至注册界面,
在注册界面,输入未注册过的用户名和密码,进行注册,提示注册成功。如果所输入的用户名已经被注册过,提示其已经注册过,请返回登录。当成功登录后,我们会跳转至个人中心。
这个人中心页面中,我们可以进行如下操作:收支管理操作,点击可以进入收支管理界面;收支查询操作,点击进入我的收支界面,进行记录查询;收支统计操作,点击进入我的收支界面,可以进行收支记录的统计;退出登录操作,点击弹出警告,是否确定退出,如果确定则退出登录,否则还是回到个人中心;
收支管理界面主要进行记录操作,分为添加、修改、修改、删除操作。添加数据操作,按照规范填写日期,类型,金额和说明,点击添加按钮进行数据添加;修改数据操作,点击列表中的任意一行,进行数据修改,依据自身需求修改数据,完成之后点击修改按钮即可完成修改操作;删除数据操作,点击列表中的任意一行,完成之后点击删除,即可对数据进行删除。
我的收支页面,可以选择日期和类型,点击搜索下方列表将显示出具体的查询结果;选择日期和类型然后点击计算,将计算出总金额。

(四)界面设计

1.用户注册界面
注册界面需要有输入账号、密码的文本框;同时还需要提交注册的按钮
在这里插入图片描述
注册点击事件关键代码:
btn_registerf.setOnClickListener(new View.OnClickListener() {…});:为注册按钮设置点击事件监听器。创建新的User对象,设置用户ID为EditText中输入的值,设置用户密码为EditText中输入的值。
DBHelper dbUserHelper = new DBHelper(getApplicationContext());:创建DBHelper对象。
if (dbUserHelper.registerUser(user) > 0) {…}:如果注册用户成功,返回值大于0。显示注册成功的提示。
如果注册用户失败,返回值小于等于0。提示"您已经注册过此账户,请返回登录", Toast.LENGTH_SHORT).show();:显示注册失败的提示。

        // 注册按键
        Button btn_registerf = findViewById(R.id.btn_registeruser);
        btn_registerf.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                User user = new User();
                user.setUserId(edt_rid.getText().toString());
                user.setUserPwd(edt_rpwd.getText().toString());

                DBHelper dbUserHelper = new DBHelper(getApplicationContext());
                if (dbUserHelper.registerUser(user) > 0) {
                    Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_SHORT).show();
                    Intent intent;
                    ArrayList<User> list = new ArrayList<>();
                    list.add(user);

                    intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
                } else {
                    Toast.makeText(getApplicationContext(), "您已经注册过此账户,请返回登录", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

2.用户登录界面
用户登录页面,需要有用户输入的账号和密码的文本框;同时还需要有用户提交登录的登录按钮,并且当是新用户时,还需要有跳转注册页面的注册按钮。
在这里插入图片描述
登录点击事件关键代码:
btn_login.setOnClickListener(new View.OnClickListener() {…});:为登录按钮设置点击事件监听器。获取用户输入的ID,获取用户输入的密码。
DBHelper dbuserHelper = new DBHelper(getApplicationContext());创建DBHelper对象。
User user = dbuserHelper.userlogin(userId, userPwd);:调用DBHelper的userlogin方法验证用户登录。如果用户不为空,表示登录成功,跳转到UserCenterActivity,如果用户为空,表示登录失败。

        // 登录按键
        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String userId = edt_id.getText().toString();
                    String userPwd = edt_pwd.getText().toString();
                    DBHelper dbuserHelper = new DBHelper(getApplicationContext());
                    User user = dbuserHelper.userlogin(userId, userPwd);

                    // 登录成功跳转到对应类型界面
                    if (user != null) {
                        Toast.makeText(getApplicationContext(), user.getUserId() + "登录成功", Toast.LENGTH_SHORT).show();
                        Intent intent;
                        ArrayList<User> list = new ArrayList<>();
                        list.add(user);

                        intent = new Intent(getApplicationContext(), UserCenterActivity.class);
                        intent.putParcelableArrayListExtra("LoginUser", list);
                        startActivity(intent);
                    } else {
                        Toast.makeText(getApplicationContext(), "登录失败,密码错误或账号不存在!", Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), "数据库异常", Toast.LENGTH_SHORT).show();
                }
            }
        });

3.个人中心界面
用户登录之后会自动跳转至个人中心页面,所以这个也相当于是一个操作页面,可以进行一些功能的选择以及账户退出等操作。主要包括提示登录用户信息的用户名,进行操作的收支管理按钮、查看收支按钮、收支统计按钮、退出登录按钮。
在这里插入图片描述
个人中心代码核心逻辑:
个人中心这个页面没有特别多的数据操作,主要的思路就是起到一个功能跳转的作用,用户通过点击不同的功能按钮来跳转不同的功能页面,以此完成整个系统的功能转换。

        // 收支管理
        ImageView btn_recordmanage = findViewById(R.id.btn_recordmanage);
        btn_recordmanage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent1 = new Intent(getApplicationContext(), ManageActivity.class);
                startActivity(intent1);
            }
        });

        // 收支查询
        ImageView btn_searchrecord = findViewById(R.id.btn_searchrecord);
        btn_searchrecord.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent2 = new Intent(getApplicationContext(), SearchRecordActivity.class);
                startActivity(intent2);
            }
        });

        // 收支统计
        ImageView btn_calcmoney = findViewById(R.id.btn_calcmoney);
        btn_calcmoney.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent3 = new Intent(getApplicationContext(), SearchRecordActivity.class);
                startActivity(intent3);
            }
        });

4.收支管理界面
进行收支管理的页面主要是进行记账信息的编辑,可以展示以后得记账信息,同时还可以进行记录的添加、修改和删除。
因此需要的内容包括一个所有收支的列表,由收支信息的序号、日期、类型、金额等;然后有一条空白的收集记录的模板,用户可以进行填写后添加,或者选中已存在的收支信息,进行编辑或者修改操作。
在这里插入图片描述
收支管理关键代码思路:
收支管理主要是进行简单的数据库操作,即用户可以选择添加一条新的记录,当用户的日期、类型、金额、备注等都不为空时,用户点击新建按钮此时就会执行添加的SQL语句,完成信息添加,然后修改和删除操作则是针对某一条记录来说,这时会先根据点击的信息的序号来进行查询,查询后的结果会被展示,然后用户可以对其进行修改和删除操作。

Button btn_update = findViewById(R.id.btn_update);
btn_update.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 无选择提示
        if (selectId == -1) {
            Toast.makeText(getApplicationContext(), "请选择要修改的行!", Toast.LENGTH_LONG).show();
            return;
        }
        // 判断是否有空数据
        if (edt_date.getText().toString().equals("") || edt_type.getText().toString().equals("") || edt_money.getText().toString().equals("") || edt_state.getText().toString().equals("")) {
            Toast.makeText(getApplicationContext(), "数据不能为空!", Toast.LENGTH_LONG).show();
            return;
        }

        String date = edt_date.getText().toString();
        String type = edt_type.getText().toString();
        String money = edt_money.getText().toString();
        String state = edt_state.getText().toString();
        // 定义修改数据的 SQL 语句
        String sql = "update " + TABLE_NAME + " set " + COLUMN_DATE + "='" + date + "',type='" + type + "',money='" + money + "',state='" + state + "' where id=" + selectId;
        // 执行 SQL 语句
        sqLiteDatabase.execSQL(sql);
        Toast.makeText(getApplicationContext(), "修改数据成功!", Toast.LENGTH_LONG).show();
        // 刷新显示列表
        selectData();
        selectId = -1;
        // 消除数据
        tv_test.setText("");
        edt_date.setText("");
        edt_type.setText("");
        edt_money.setText("");
        edt_state.setText("");
    }
});

5.收支统计界面
关于收支统计页面,首先这是一个专门对收支记录进行查询的一个界面,因此主要是分类和查询的操作。能够根据日期和类型进行分类,同时可以搜索某一日期的收支信息,或者只查看收入或支出,同时还能够计算出某月净收入等。
在这里插入图片描述
收支统计关键代码思路:
用户选择的查询条件,动态生成 SQL 查询语句。这个逻辑用于 selectData 和 selectSumMoney 方法中。通过这些方法,能够从数据库中查询数据,并根据查询结果进行相应处理。

//定义查询的 SQL 语句
String sql;
// 如果查询时间和查询类型都为空,则查询整个表
if (TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
    sql = "select * from " + TABLE_NAME;
} else if (!TextUtils.isEmpty(selectDate) && TextUtils.isEmpty(selectType)) {
    // 如果有查询时间,没有查询类型,查询指定内容
    sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "'";
} else if (TextUtils.isEmpty(selectDate) && !TextUtils.isEmpty(selectType)) {
    // 如果没有查询时间,有查询类型,查询指定内容
    sql = "select * from " + TABLE_NAME + " where type='" + selectType + "'";
} else {
    // 否则,查询条件都不为空,查询指定内容
    sql = "select * from " + TABLE_NAME + " where date='" + selectDate + "' and type='" + selectType + "'";
}

五、实验结果

电脑实验错误


首先通过电脑进行测试,结果发现要进行收支类型的填写时,无法输入中文。

实验过程


最后通过手机进行合适的测试。

六、问题与解决方案

问题一:电脑运行测试时,输入法无法输入中文

解决方法:用Android studio配置真机,用手机进行直接操作,通过手机进行账单记录类型的中文输入。
这里需要注意根据手机型号的不同,真机配置的方法可能不一样,例如我的是华为手机,当我用USB连接后就会自动提示下载华为手机助手,这个助手下载之后就连不上真机了,具体原理不知道为什么,必须将手机和电脑中的这个软件卸载才能通过USB调试;来完成在真机上运行。

问题二:在计算收支的总金额时,出现加减法不正确的问题

解决方法:这个是因为开始的疏忽大意,没有正确匹配收支类型来进行计算,导致加法的过程出现结果错误,这里我通过修改收支管理页面的统计代码来实现正确的结果。

while (cursor.moveToNext()) {
float money = cursor.getFloat(cursor.getColumnIndex(COLUMN_MONEY));
String type = cursor.getString(cursor.getColumnIndex(COLUMN_TYPE));
            
if ("收入".equals(type)) {
                sum += money;
} else if ("支出".equals(type)) {
                sum -= money;
            }
        }

String money2 = String.valueOf(sum);
tv_show.setText(money2);

问题三:当数据量较大时,会出现数据显示不完整的问题。

解决方法:使用合适的布局方式和控件,使用 ScrollView 包裹 ListView 来实现数据的滚动显示。

七、学习心得与课程总结

学习心得:
本次实验相对于之前有明确的目标指向,这次实验更加侧重于我们自己的发挥与设计,对我们的考验比较大,不仅需要我们有好的、可实现的想法,还需要对自己的程序有更加全面深刻的构思,这需要我们对版本学期的知识融汇贯通。
本次实验我没有选择调用一些网络上提供的组件,实现一些深层次的效果,我主要是侧重于对sqlite数据库的运用。我深刻体会到了数据库操作在移动应用开发中的重要性和实用性。通过学习和实践,我掌握了使用 SQLite 数据库进行数据存储和操作的基本方法,以及如何在 Android 应用中有效地管理和展示数据。
在实验中,我遇到了一些挑战,比如在设计数据库表结构和编写 SQL 查询语句时需要考虑数据的一致性和有效性,同时还要避免出现逻辑错误和性能问题。另外,在界面设计和用户交互方面,我也遇到了一些问题,需要不断调整和优化,以提高用户体验。
通过解决这些问题,我不仅加深了对数据库操作和 Android 应用开发的理解,还提升了自己的问题解决能力和代码调试技巧。这次大作业让我收获颇丰,不仅对一些重要的知识进行了巩固与熟练与运用,同时我对如何架构起一个较为完整的APP有了更加深层次的理解,收获很大。

课程总结:
很高兴本学期能够选上王老师的移动平台开发与实践课程,虽然开始报这个课前,对移动平台这个没有过多深入的了解,完全是由于强哥的个人魅力去选择这门课,通过强哥一学期的指导,确实让我收获颇多,至少提到移动平台开发与实践,我的脑袋里不会只有安卓、手机、这种较为浅层的东西,我能够说出Activity、Service、BroadcastReceiver和ContentProvider这四大组件,并且实践了这四大组件的使用,能够描述出他们分别是什么内容:Activity:学习了Activity的生命周期管理和页面跳转。Service:实现了一个后台服务,理解了Service的启动模式和生命周期。BroadcastReceiver:通过实现广播接收器,掌握了广播机制和动态注册。ContentProvider:学习了如何在应用之间共享数据。然后还能结合上学期的网编知识,知道如何在Android studio中实现socket编程,包括Socket的创建、连接、数据传输等。然后我还学到了如何站在巨人的肩膀上,尝试调用其他的api进行一些高级功能的实现,这些实验不仅让我掌握了丰富的技术知识,还培养了我的问题解决能力和创新思维,为我未来的Android开发之路奠定了坚实的基础。最后,非常感谢王老师一学期的指导与帮助让我收获良多!

  • 26
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值