Android development: write a simple ledger based on Android Studio

table of Contents

Preface

The program being written recently involves user registration/login and SQLite database operations. So I sorted out the code I wrote and wrote a simple account book demo. The main functions include: user registration/login, user new fund records (including amount, time, user name), display of all fund records, and all data storage uses SQLite database. The current function is relatively rough, and everyone is welcome to discuss improvements.

User registration/login

For the drawing of the registration/login interface, please refer to my previous article:
Android Development: Writing the Login/Registration Interface.
The drawing of the interface is described in detail. Only the main code in Activity is posted in this article.
In this module, two methods are written to query the information indexed by the current user name (including whether the user exists and the user's password) for judgment; and to insert one into the table of user information in the database New record (used to realize the registration function).
The first method:

String queryUser(String Username){
        //查询结果
        String res = "";
        //数据库声明
        SQLiteDatabase mDbUser;
        Cursor Count_cursor;
        //对存储于手机本地的记录进行读取
        mDbUser = openOrCreateDatabase("upCount.db", Context.MODE_PRIVATE, null);
        mDbUser.execSQL("CREATE TABLE IF NOT EXISTS user (_id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR, password VARCHAR)");
        Count_cursor = mDbUser.rawQuery("SELECT * FROM user WHERE _id >= ?", new String[]{"1"});
        //若查询到当前用户,则退出
        while (Count_cursor.moveToNext()){
            String username = Count_cursor.getString(Count_cursor.getColumnIndex("username"));
            if (username.equals(Username)){
                res = Count_cursor.getString(Count_cursor.getColumnIndex("password"));
            }
        }
        //关闭数据库连接
        Count_cursor.close();
        mDbUser.close();
        return res;
    }

The second method:

void createUser(String Username, String Password){
        //数据库声明
        SQLiteDatabase mDbUser;
        //SQLite数据库处理
        mDbUser = openOrCreateDatabase("upCount.db",  Context.MODE_PRIVATE, null);
        mDbUser.execSQL("CREATE TABLE IF NOT EXISTS user (_id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR, password VARCHAR)");
        mDbUser.execSQL("INSERT INTO user VALUES (NULL, ?, ?)",new Object[]{Username, Password});
        //关闭数据库连接
        mDbUser.close();
    }

The code of the click event is as follows:
(1) "Register" Button:

//点击注册,触发点击事件
        mBtnRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取用户输入的账号及密码,传送到服务器进行判断
                Username = mEtUsername.getText().toString();
                Password = mEtPassword.getText().toString();
                //确保用户输入不为空值
                if (Username.equals("")){
                    Toast.makeText(getApplicationContext(), "用户名不能为空!", Toast.LENGTH_SHORT).show();
                }else if(Password.equals("")){
                    Toast.makeText(getApplicationContext(), "密码不能为空!", Toast.LENGTH_SHORT).show();
                }else {
                    if(!queryUser(LoginActivity.Username).equals("")){
                        Toast.makeText(getApplicationContext(), "该用户已存在!", Toast.LENGTH_SHORT).show();
                    }else{
                        createUser(LoginActivity.Username, Password);
                        Toast.makeText(getApplicationContext(), "注册成功!", Toast.LENGTH_SHORT).show();
                        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                        startActivity(intent);
                    }
                }
            }
        });

(2) "Login" Button:

//点击登录,触发点击事件
        mBtnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取用户输入的账号及密码,传送到服务器进行判断
                Username = mEtUsername.getText().toString();
                Password = mEtPassword.getText().toString();
                //确保用户输入不为空
                if (Username.equals("")){
                    Toast.makeText(getApplicationContext(), "用户名不能为空!", Toast.LENGTH_SHORT).show();
                }else if(Password.equals("")){
                    Toast.makeText(getApplicationContext(), "密码不能为空!", Toast.LENGTH_SHORT).show();
                }else {
                    //调用用户信息查询方法
                    String rightPassword = queryUser(LoginActivity.Username);
                    if(rightPassword.equals("")){
                        Toast.makeText(getApplicationContext(), "该用户不存在,请注册!", Toast.LENGTH_SHORT).show();
                    }else{
                        if (Password.equals(rightPassword)){
                            Toast.makeText(getApplicationContext(), "登录成功!", Toast.LENGTH_SHORT).show();
                            Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                            startActivity(intent);
                        }else{
                            Toast.makeText(getApplicationContext(), "密码错误!", Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            }
        });

Note: In the click event, the Username and Password should be judged as non-empty first to prevent the user from clicking the button without entering the complete information, which may cause illegal values ​​to be entered into the database.

New funds record

The new fund record includes three parts: obtaining the current system time, obtaining the user's input fund value, and writing data to the database. The specific code is as follows:

//记录账单
        mBtnRecord.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取当前时间
                date = new Date(System.currentTimeMillis());
                time = sdf.format(date);
                Toast.makeText(getApplicationContext(), "Current Time:" + time, Toast.LENGTH_SHORT).show();
                //获取用户输入的金额
                String count = mEtCount.getText().toString();
                //SQLite数据库处理
                mDbCount = openOrCreateDatabase("upCount.db",  Context.MODE_PRIVATE, null);
                mDbCount.execSQL("CREATE TABLE IF NOT EXISTS count (_id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR, time VARCHAR, count VARCHAR)");
                mDbCount.execSQL("INSERT INTO count VALUES (NULL, ?, ?, ?)",new Object[]{LoginActivity.Username, time, count});
                mDbCount.close();
            }
        });

Query all fund records of the current user

In the demo, ListView is used as the container for record display. The writing steps mainly include declaring controls, writing adapters, etc. Due to space reasons, I will not repeat them here. Only the part that involves data reading is shown here. The code is as follows:

//对存储于手机本地的记录进行读取
        mDbCount = openOrCreateDatabase("upCount.db", Context.MODE_PRIVATE, null);
        mDbCount.execSQL("CREATE TABLE IF NOT EXISTS count (_id INTEGER PRIMARY KEY AUTOINCREMENT, username VARCHAR, time VARCHAR, count VARCHAR)");
        Count_cursor = mDbCount.rawQuery("SELECT * FROM count WHERE _id >= ?", new String[]{"1"});
        while (Count_cursor.moveToNext()){
            String username = Count_cursor.getString(Count_cursor.getColumnIndex("username"));
            //if语句:使界面只展示目前登录用户的爬楼梯记录
            if (username.equals(LoginActivity.Username)){
                UpList upList = new UpList();
                upList.setUsername(username);
                upList.setTime(Count_cursor.getString(Count_cursor.getColumnIndex("time")));
                upList.setCount(Count_cursor.getString(Count_cursor.getColumnIndex("count")));
                upLists.add(upList);
            }
        }

The implementation logic is to first use the pointer to traverse the corresponding table in the database, add the data whose "username" field value in the table is the same as the current user name to a collection list, and then display it on the interface through the adapter.

Demo interface display

(1) Registration/Login interface:

Registration/Login Interface


(2) Main interface:

Main interface


(3) Record display interface:

Record display interface

postscript

There are a lot of the above codes, so it is recommended that you implement the functions in modules, so that when an error occurs, it is easier to determine which module has a problem. Due to space reasons, I didn't post all the code in this article at once, so I can only trouble you guys to integrate it yourself. I will also upload the source code and the entire project file in a package later, and partners in need can download it by themselves. If you have any questions, you can comment below and I will try my best to reply to you. If you don’t have points, you can search for my personal official account "Chaqian" on WeChat or scan the picture below. After paying attention, reply to "Ledger" in the background, and you can get the source code directly. I usually post some programming-related articles on the public account, welcome everyone to pay attention~

Chaqian