【1个月速成Java】基于Android平台开发个人记账app学习日记——第4天,注册登录功能设计

24.11.03

1.修改项目目录

从今天开始将正式进行功能的设计,首先需要对原来的项目结构进行修改,主要是添加新的文件夹用于存放新的文件。下面进行展示和讲解:

我用红圈圈出了新添加的文件夹,介绍下它们都是干啥的:

  • data:负责应用数据的管理。

    • model:定义数据模型类,比如 Expense 表示支出记录。
    • database:存放与数据库相关的代码。ExpenseDatabase 是 Room 数据库类,ExpenseDao 是用于定义数据库查询的接口。
  • ui:负责 UI 层的代码。

    • activity:放置主界面 Activity,如 MainActivity
    • fragment:每个页面或子模块用一个 Fragment,比如 OverviewFragment 展示支出概览,AddExpenseFragment 添加新的支出记录。
    • adapter:RecyclerView 适配器,例如 CategoryAdapter,用于展示分类支出的列表。
    • theme:存放主题文件,如颜色、字体和样式的配置。
    • viewmodel:放置 ViewModel 类,负责管理 UI 所需的数据逻辑。例如 MainViewModel 用于管理首页的数据,ExpenseViewModel 用于管理支出记录。
  • util:放置工具类,例如 DateUtils 用于日期格式化等辅助功能。

  • res:包含所有的资源文件。

    • layout:XML 布局文件,比如 activity_main.xml 是主界面的布局,fragment_overview.xmlfragment_add_expense.xml 是 Fragment 的布局。

 目前就只需要做这些更改,下面基于这些进行开发

2.调整依赖项文件

可以看到整个项目用的是kotlin语言,所以需要一步步转换成Java的,首先从依赖项文件build.gradle.kts入手,把它的内容转换成build.gradle,也就是将 Kotlin DSL (build.gradle.kts) 转换为 Groovy DSL (build.gradle),Kotlin DSL (build.gradle.kts) 和 Groovy DSL (build.gradle) 是 Android Gradle 构建系统中用于定义构建脚本的两种不同语言,具体细节大家自己查询进一步了解。

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
    namespace 'com.example.personalexpensetracker'
    compileSdk 34

    defaultConfig {
        applicationId "com.example.personalexpensetracker"
        minSdk 24
        targetSdk 34
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
    }

    buildTypes {
        release {
            minifyEnabled false // 这里不再使用 isMinifyEnabled
            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
        }
    }
    
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
    
    buildFeatures {
        compose = true
    }
    
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }
    
    packaging {
        resources {
            excludes += "/META-INF/{AL2.0,LGPL2.1}"
        }
    }
}

dependencies {
    implementation libs.androidx.core.ktx
    implementation libs.androidx.lifecycle.runtime.ktx
    implementation libs.androidx.activity.compose
    implementation platform(libs.androidx.compose.bom)
    implementation libs.androidx.ui
    implementation libs.androidx.ui.graphics
    implementation libs.androidx.ui.tooling.preview
    implementation libs.androidx.material3
    implementation libs.androidx.appcompat
    
    // 添加 Room 依赖项
    implementation 'androidx.room:room-runtime:2.4.3'
    annotationProcessor 'androidx.room:room-compiler:2.4.3' // Java项目

    // 如果是Kotlin项目,使用下面的行
    // kapt 'androidx.room:room-compiler:2.4.3'

    testImplementation libs.junit
    androidTestImplementation libs.androidx.junit
    androidTestImplementation libs.androidx.espresso.core
    androidTestImplementation platform(libs.androidx.compose.bom)
    androidTestImplementation libs.androidx.ui.test.junit4
    debugImplementation libs.androidx.ui.tooling
    debugImplementation libs.androidx.ui.test.manifest
}

文件转换完以后重新构建一下,同时我添加了用于操作数据库的依赖项ROOM,大家可以把这个理解为python中用pip安装需要的包一样。 

3.创建用户类

完成依赖项的安装后,为了实现登录注册功能,肯定需要使用数据库来存储相关数据,而管理这些数据最合适的数据模型就是构建一个用户类,因为是一个个用户进行登录注册,所以在用户类中定义每个用户的数据项即可。我们在data下的model中创建一个User.java文件,来表示用户类。

下面是具体代码,其中的Java语法包括:

  1. 类定义

    public class User:定义了一个名为 User 的公共类,任何其他类都可以访问。
  2. 注解

    注解(如 @Entity@PrimaryKey)是元数据,用于提供关于代码元素(如类、方法、字段)的额外信息。
  3. 访问修饰符

    public:表示该类或方法对所有其他类可见。private:表示字段只能在类内部访问,封装了数据,保护了类的内部状态。
  4. 构造函数

    构造函数的名称与类名相同,用于初始化对象的状态。
  5. 方法

    方法是执行特定操作的代码块。Getter 和 Setter 是常见的 Java 方法,常用于访问和修改私有属性。
import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity(tableName = "users")
public class User {
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String username;
    private String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    // Getter 和 Setter 方法
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

4.创建DAO

在 Android 中,DAO(Data Access Object)是一个接口或抽象类,用于定义与数据库交互的方法。DAO 是 Room 数据库架构组件的一个重要部分,负责提供对数据库的访问,以便进行增删改查(CRUD)操作。我们创建一个新的包名为dao,里面存放dao文件。

package com.example.personalexpensetracker.data.dao;

import com.example.personalexpensetracker.data.model.User;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;

@Dao
public interface UserDao {
    @Insert
    void insert(User user);

    @Query("SELECT * FROM users WHERE username = :username AND password = :password LIMIT 1")
    User login(String username, String password);
}

5.创建Room数据库

AppDatabase 类用于定义 Room 数据库的基本信息,包括数据库包含的实体和访问 DAO 的方法。该类通常放在 database 包中,以便于管理。

package com.example.personalexpensetracker.data.database;

import com.example.personalexpensetracker.data.dao.UserDao;
import com.example.personalexpensetracker.data.model.User;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import android.content.Context;

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    private static AppDatabase instance;

    public abstract UserDao userDao();

    public static synchronized AppDatabase getInstance(Context context) {
        if (instance == null) {
            instance = Room.databaseBuilder(context.getApplicationContext(),
                            AppDatabase.class, "user_database")
                    .fallbackToDestructiveMigration()
                    .build();
        }
        return instance;
    }
}

至此我们就简单的把用户数据模型和基础的数据库操作结构配置完毕,当然后续需要再更改,当前写的更多是为了项目完整和便于理解学习。

6.分别创建注册和登录界面xml文件

接下来我们分别把注册和登录界面的布局文件创建好,写在res/layout文件夹中。

activity_register.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:padding="16dp">

    <EditText
            android:id="@+id/phoneEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="请输入手机号"
            android:inputType="phone"/>

    <CheckBox
            android:id="@+id/agreeCheckBox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="已阅读并同意《用户协议》和《隐私协议》"/>

    <Button
            android:id="@+id/registerButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="注册"/>
</LinearLayout>

activity_login.xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:padding="16dp">

    <EditText
            android:id="@+id/etUsername"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="用户名" />

    <EditText
            android:id="@+id/etPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="密码"
            android:inputType="textPassword" />

    <Button
            android:id="@+id/btnLogin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="登录" />

    <TextView
            android:id="@+id/tvRegister"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="没有账户? 注册"
            android:layout_marginTop="16dp" />
</LinearLayout>

 启动测试效果如下:

可以看到页面启动成功,我们下面先把逻辑代码编写完成,然后再调整ui。具体逻辑包括注册后数据保存;首次注册后直接进入主页;下次启动判断是否需要再次登录还是直接进入主页;登录界面输入密码登录;高阶操作包括用手机号注册。

篇幅所限,下篇文章见。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907354.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动态库实现lua网络请求GET, POST, 下载文件

DLL需要使用的网络封装 WinHttp异步实现GET, POST, 多线程下载文件_webclient post下载文件-CSDN博客文章浏览阅读726次。基于WinHttp封装, 实现异步多线程文件下载, GET请求, POST请求_webclient post下载文件https://blog.csdn.net/Flame_Cyclone/article/details/142644088…

unet中的attn_processor的修改(用于设计新的注意力模块)

参考资料 文章目录 unet中的一些变量的数据情况attn_processorunet.configunet_sd 自己定义自己的attn Processor &#xff0c;对原始的attn Processor进行修改 IP-adapter中设置attn的方法 参考的代码&#xff1a; 腾讯ailabipadapter 的官方训练代码 unet中的一些变量的数据…

深度学习基础—序列采样

引言 深度学习基础—循环神经网络&#xff08;RNN&#xff09;https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link …

Qt中的Model与View5: QStyledItemDelegate

目录 QStyledItemDelegate API 重载公共函数 保护函数 重载保护函数 当在 Qt 项目视图中显示模型数据时&#xff0c;例如 QTableView&#xff0c;每个项目由代理绘制。此外&#xff0c;当项目被编辑时&#xff0c;提供一个编辑器小部件&#xff0c;该小部件在编辑时显示在项…

AI打造超写实虚拟人物:是科技奇迹还是伦理挑战?

内容概要 在这个科技飞速发展的时代&#xff0c;超写实虚拟人物仿佛从科幻小说中走进了我们的日常生活。它们以生动的形象和细腻的动作&#xff0c;不仅在影视、广告和游戏中吸引了无数目光&#xff0c;更让我们对AI技术的未来充满了期待和疑惑。这些数字化身在逼真的外貌下&a…

海浪中的记忆:海滨学院班级回忆录开发

3系统分析 3.1可行性分析 通过对本海滨学院班级回忆录实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本海滨学院班级回忆录采用SSM框架&#xff0c;JAVA作为开…

文本串的应用(1)

一、文本串的加密解密操作 一个文本串可用事先给定的字母映射表进行加密。 例如&#xff0c;假设字母映射表为&#xff1a; a b c d e f g h i j k l m n o p q r s t u v w x y z n g z q t c o b m u h e l k p d a w x f y i v r s j 则字符串“encrypt”被加密为“tkz…

MCU裸机任务调度架构

第1章 方式一(平均主义) int main(int argc, char **argv){/* RTC 初始化 */bsp_RTC_Init(&rtc);/* 串口初始化 */uartInit(115200);/* LED初始化 */ledInit();while(1){// 任务1(获取传感器数据)// 任务2// 任务3} } 1.1 平均主义的缺陷 获取传感器数据可以600ms去读取一…

【力扣专题栏】面试题 01.02. 判定是否互为字符重排,如何利用数组模拟哈希表解决两字符串互排问题?

题解目录 1、题目描述解释2、算法原理解析3、代码编写(1)、两个数组分别模拟哈希表解决(2)、利用一个数组模拟哈希表解决问题 1、题目描述解释 2、算法原理解析 3、代码编写 (1)、两个数组分别模拟哈希表解决 class Solution { public:bool CheckPermutation(string s1, stri…

【OJ题解】C++实现反转字符串中的每个单词

&#x1f4b5;个人主页: 起名字真南 &#x1f4b5;个人专栏:【数据结构初阶】 【C语言】 【C】 【OJ题解】 题目要求&#xff1a;给定一个字符串 s &#xff0c;你需要反转字符串中每个单词的字符顺序&#xff0c;同时仍保留空格和单词的初始顺序。 题目链接: 反转字符串中的所…

全新更新!Fastreport.NET 2025.1版本发布,提升报告开发体验

在.NET 2025.1版本中&#xff0c;我们带来了巨大的期待功能&#xff0c;进一步简化了报告模板的开发过程。新功能包括通过添加链接报告页面、异步报告准备、HTML段落旋转、代码文本编辑器中的文本搜索、WebReport图像导出等&#xff0c;大幅提升用户体验。 FastReport .NET 是…

【数据结构与算法】第8课—数据结构之二叉树(堆)

文章目录 1. 树1. 什么是树&#xff1f;1.2 树的相关概念1.3 树的表示法 2. 二叉树2.1 特殊的二叉树2.2 二叉树的性质2.3 二叉树的存储结构 3. 实现顺序结构二叉树3.1 堆的概念3.2 堆的实现3.2.1 堆的数据结构3.2.2 堆的初始化3.2.3 堆插入数据3.2.4 删除堆顶数据3.2.5 堆的判空…

Spring的高效开发思维(三)

时间&#xff1a;2024年 11月 02日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频&#xff1a;喜马拉雅 大家好&#xff0c;欢迎来到“小蒋聊技术” 我是小蒋&#xff01;。小蒋今天想和大家聊聊Spring Cloud微服务架构&am…

TEC半导体致冷工作原理:【图文详讲】

目录 1&#xff1a;什么是TEC 2&#xff1a;TEC工作原理 3&#xff1a;TEC结构 4&#xff1a;TEC技术参数 5&#xff1a;TEC选型 6&#xff1a;实物TEC 7&#xff1a;手机散热器 1&#xff1a;什么是TEC TEC半导体致冷器&#xff08;Thermo Electric Cooler&#xff09…

Linux开发讲课47--- 详解 Linux 中的虚拟文件系统

虚拟文件系统是一种神奇的抽象&#xff0c;它使得 “一切皆文件” 哲学在 Linux 中成为了可能。 什么是文件系统&#xff1f;根据早期的 Linux 贡献者和作家 Robert Love 所说&#xff0c;“文件系统是一个遵循特定结构的数据的分层存储。” 不过&#xff0c;这种描述也同样适用…

海的记忆篇章:海滨学院班级回忆录项目

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了海滨学院班级回忆录的开发全过程。通过分析海滨学院班级回忆录管理的不足&#xff0c;创建了一个计算机管理海滨学院班级回忆录的方案。文章介绍了海滨学院班级回…

【WebRTC】WebRTC的简单使用

目录 1.下载2.官网上的使用3.本地的使用 参考&#xff1a; 【webRTC】一、windows编译webrtc Windows下WebRTC编译 1.下载 下载时需要注意更新python的版本和网络连接&#xff0c;可以先试试ping google。比较关键的步骤是 cd webrtc-checkout set https_proxy127.0.0.1:123…

【05】如何解决tomcat命令提示符控制台乱码问题

Web项目开发过程中&#xff0c;直接在命令提示符窗口中通过输入startup.bat命令运行tomcat&#xff0c;在新弹出的tomcat命令提示符窗口中输出的中文是乱码问题的处理。 如何解决tomcat命令提示符控制台乱码问题 文章目录 如何解决tomcat命令提示符控制台乱码问题1.解决问题思路…

Golang | Leetcode Golang题解之523题连续的子数组和

题目&#xff1a; 题解&#xff1a; func checkSubarraySum(nums []int, k int) bool {m : len(nums)if m < 2 {return false}mp : map[int]int{0: -1}remainder : 0for i, num : range nums {remainder (remainder num) % kif prevIndex, has : mp[remainder]; has {if …

JeecgBoot集成工作流实战教程

Activiti是一个轻量级的工作流程和业务流程管理&#xff08;BPM&#xff09;平台&#xff0c;它主要面向业务人员、开发人员和系统管理员。这个平台的核心是一个快速且可靠的Java BPMN 2流程引擎。Activiti是开源的&#xff0c;并且基于Apache许可证进行分发。它可以运行在任何…