拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Android无数据库版个人信息注册:Activity与Intent传值入门实战

简介这是一份基于Android Studio开发的轻量级用户注册功能实践项目面向移动应用开发初学者帮助理解Android基础UI组件与页面跳转逻辑。项目实现用户名、密码输入性别单选、地址下拉选择、爱好复选框等典型表单交互并完成空值校验与结果页数据回显支持结果页返回首页无需后端数据库适合课堂实验或自学入门。压缩包共495个文件包含88个XML布局与配置文件、134个Flat资源文件、128个JSON配置及20个WebP图片资源辅以Java源码5个.java文件、APK安装包及Gradle构建脚本整体体积10.27MB结构完整、即下即用。已有846人学习下载配套代码规范、注释清晰涵盖Activity生命周期管理、Intent传参、控件事件监听等核心知识点可直接导入Android Studio运行调试是掌握Android基础开发流程的理想参考实例。 很多初学者在Android Studio里做的第一个练手项目往往是“个人信息注册”。网上搜出来的教程十有八九是搭配数据库的SQLite、Room、MySQL一起上还没开始写界面就被配置和各种依赖搞得头大。其实在入门阶段完全可以用无数据库的方式先把“界面搭建—数据获取—页面跳转—数据展示”这条主链路跑通等理解了Activity、Intent、控件监听这些基础概念之后再决定要不要引入数据库。这个项目非常适合刚学完Activity和Intent、想动手练练控件监听和数据传递的同学。做完之后你会对EditText、RadioGroup、CheckBox、Spinner这些常用表单控件有很直观的理解也能搞清楚对象封装和列表展示是怎么一回事。下面我把自己实现这个项目的完整思路、代码和踩坑经验整理出来给大家做一个参考。1. 项目概述与整体设计思路1.1 核心需求解析先明确一下这个项目要做什么界面上有姓名、年龄、性别、联系方式、兴趣爱好几个输入项用户填完后点“注册”进入另一个页面看到刚才填的信息或者返回一个“注册成功”的提示。最核心的一点是数据只存在内存里不写数据库也不做持久化存储。需求拆解下来就三块表单界面包含输入框、单选按钮组、复选框组控件之间排列整齐。数据获取与校验点击按钮后把界面上填的内容提取出来做必要的格式检查比如手机号位数、年龄是否数字。数据展示把获取到的信息通过Intent传递到第二个Activity用TextView或者列表展示出来。这种“一个页面收集数据另一个页面展示数据”的结构几乎覆盖了Android开发前几个月的所有核心知识点。做完这个项目再看别的教程就会轻松很多。1.2 为什么选择“无数据库版”做入门很多人有个误区觉得注册功能必须要有数据库否则就“不完整”。但先想一个问题你学Android的第一天连Activity的生命周期还没搞清楚接口怎么调也不知道这时候硬塞一个数据库进来其实是给自己增加负担。无数据库版本最大的好处是降低认知负担。不用管数据库连接、建表语句、增删改查也不需要考虑异步线程把全部注意力放在界面和交互上。等你跑通了整个注册流程知道“用户点按钮的时候代码该做什么”再回头去学SQLite数据库就很自然了无非是把原来存在内存里的User对象换一种方式写到本地文件里而已。内存数据的局限也很明显Activity一旦销毁数据就没了应用退出重进数据也没了。这正好是后面学习数据持久化的切入点。我用这个项目给学员讲课时经常说一句话“先让数据在内存里跑起来再考虑让它活得更久。”1.3 方案选型对比实现“个人信息注册”可以选几种方式这里把常见的方案列个对比方案数据存储方式复杂度适用场景Intent传值 新页面展示内存临时数据随Activity销毁而消失低入门练手、课堂作业、验证明白数据流单例/静态List保存 RecyclerView展示应用运行期间数据保留进程终止就清空中低无数据库版的多条记录展示SharedPreferences保存键值对方式持久化适合少量简单数据中已掌握基础想保存登录状态SQLite / Room本地关系型数据库数据结构化存储高正式项目、有查询条件需求这个项目标题明确说了“无数据库版”所以我建议采用前两种单条数据显示时直接靠Intent传值多个注册用户时用静态List暂存再用RecyclerView或ListView展示。后面的代码示例会同时给出这两种情况的实现思路。1.4 技术栈与基础工具检查开始动手前确认一下电脑上的环境Android Studio版本建议用较新的稳定版例如新版北极狐或以上版本老版本也没问题代码本身不涉及新特性。JDK版本Android Studio自带JBR通常不用单独配置。模拟器或真机建议准备一台真机或者API等级30以上的模拟器方便调试。不需要额外下载数据库工具这也是无数据库版最轻松的地方。如果你现在还在为Android Studio安装、Gradle下载慢这些问题折腾先花点时间把环境搞定再回来看代码不然编译报错会消耗掉你大半的耐心。2. 界面搭建布局文件与控件实战2.1 布局选型LinearLayout够用但推荐学一下ConstraintLayout整个注册界面是典型的纵向表单结构所以布局方案很清晰外层用一个垂直方向的LinearLayout是最直白的做法每一行放一个控件或者一个“标签输入框”的组合。如果只是做这个作业LinearLayout完全够用。但我更推荐用ConstraintLayout来搭原因有两个一是现在Android官方模板默认都用ConstraintLayout照着学不会过时二是ConstraintLayout配合链Chain和约束处理控件对齐、间距比LinearLayout嵌套更优雅。不过看代码的时候不用慌LinearLayout能实现的效果ConstraintLayout基本都能实现后面优化时转换成本也不高。下面是我常用的一个布局结构最外层LinearLayout android:layout_widthmatch_parent android:layout_heightmatch_parent android:orientationvertical android:padding16dp里面依次放姓名输入框、年龄输入框、性别单选组、联系方式输入框、兴趣复选框组、注册按钮。整体是自上而下的单列结构不需要复杂的嵌套。2.2 控件组合理清与属性要点先看每一个控件要用的关键属性。姓名和联系方式用EditText。年龄也用EditText但要限制输入内容为数字。设置方式有两种布局文件里用android:inputTypenumber或者代码里给EditText设置setInputType(InputType.TYPE_CLASS_NUMBER)。inputType的好处是弹出的软键盘就是数字键盘能减少用户输入非法字符的概率。性别用RadioGroup包两个RadioButtonAndroid里单选组必须由RadioGroup管理这一点和Web前端的name分组是一样的思路。关键属性是RadioGroup android:idid/rgGender android:orientationhorizontal RadioButton android:idid/rbMale android:text男 / RadioButton android:idid/rbFemale android:text女 / /RadioGroup获取选中值时可以调用radioGroup.getCheckedRadioButtonId()拿到选中按钮的id再通过findViewById得到对应的RadioButton文字。如果没选中这个方法会返回-1处理时要注意判空。兴趣爱好看需求可以用CheckBox做多选也可以用Spinner做单选下拉。个人觉得CheckBox更贴近“爱好多选”的语义。布局里放几个CheckBoxCheckBox android:idid/cbReading android:text阅读 / CheckBox android:idid/cbMusic android:text音乐 /获取多个复选框状态时逐个用isChecked()判断然后把选中的文本拼接进一个String。这块逻辑要写在按钮的点击事件里不要写在onCreate里不然用户还没操作就取到了空值。2.3 strings.xml资源与样式细节界面上的文字建议不要硬编码在布局文件里而是放到res/values/strings.xml中。例如string namelabel_name姓名/string string namelabel_age年龄/string string namelabel_gender性别/string string namebtn_register注册/string布局里用string/label_name引用。这样做的好处有两个第一是后面如果需要做多语言不需要改布局第二是代码和文本解耦改提示语的时候不用翻整个XML。很多初学者没这个意识所有提示文字直接写死在布局里虽然不影响运行但工程上不推荐。样式方面给每个输入区块加一个左侧标签常见写法是“TextView EditText”放在一个水平LinearLayout里或者用TableLayout做表单对齐。用TableLayout做“左侧标签、右侧输入”的表单其实很顺手但写起来略啰嗦。这里我采用“每一行一个竖直排列”的方式标签在上、输入框在下手机屏幕窄这样排列更不容易挤。2.4 预览布局时容易忽略的两个细节一是键盘弹出问题。当EditText获得焦点时软键盘会把下面的按钮顶上去或者遮挡。可以在AndroidManifest.xml的Activity节点上加android:windowSoftInputModeadjustResize让布局在键盘弹出时自动压缩。如果跑下来发现键盘弹出把注册按钮挡得严严实实再检查一下是不是漏了这个属性。二是默认焦点问题。布局里第一个EditText在页面打开时会自动弹出键盘可以让它后面再弹也可以在根布局上设置android:focusabletrue和android:focusableInTouchModetrue把初始焦点从输入框身上移走。这个小细节很多人不做体验差别很大。3. 核心逻辑实现从输入到展示3.1 User对象封装为什么不直接塞一堆String点击注册按钮后界面上有五个数据姓名、年龄、性别、手机号、兴趣。最粗暴的做法是用Intent分别putExtra五个字符串然后在下一个Activity里逐个getStringExtra。但这种写法有明显的坏处数据字段一多Intent的代码会越写越长语义也不清晰别人读代码的时候很难一眼看出“这些String是一个整体”。更好的做法是把这些字段封装成一个User类。这样Intent只需要放一个对象第二个Activity取出来直接用代码结构清晰很多。public class User implements Serializable { private String name; private String age; private String gender; private String phone; private String hobbies; public User(String name, String age, String gender, String phone, String hobbies) { this.name name; this.age age; this.gender gender; this.phone phone; this.hobbies hobbies; } // 生成对应的getter/setter方法 public String getName() { return name; } public String getAge() { return age; } public String getGender() { return gender; } public String getPhone() { return phone; } public String getHobbies() { return hobbies; } }注意这里实现了Serializable接口。Intent如果要传递Java对象对象必须实现Serializable或者使用Parcelable。Serializable实现起来最简单直接加一个接口标记就行缺点是性能不如Parcelable。但在这种练手项目里Serializable完全够用不用过度设计。3.2 注册按钮点击事件的完整逻辑注册按钮的点击事件是这个项目最核心的代码块逻辑一般分四步获取各个控件的实例。从EditText里取字符串从RadioGroup和CheckBox里取选中状态。做基础校验不合格就用Toast提示。封装User对象用Intent跳转或加入列表。先看获取控件实例。在onCreate里通过findViewById拿到所有控件随后给按钮设置监听Button btnRegister findViewById(R.id.btn_register); btnRegister.setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { EditText etName findViewById(R.id.et_name); EditText etAge findViewById(R.id.et_age); EditText etPhone findViewById(R.id.et_phone); RadioGroup rgGender findViewById(R.id.rg_gender); CheckBox cbReading findViewById(R.id.cb_reading); CheckBox cbMusic findViewById(R.id.cb_music); String name etName.getText().toString().trim(); String age etAge.getText().toString().trim(); String phone etPhone.getText().toString().trim(); int checkedId rgGender.getCheckedRadioButtonId(); String gender ; if (checkedId ! -1) { RadioButton rb findViewById(checkedId); gender rb.getText().toString(); } StringBuilder hobbies new StringBuilder(); if (cbReading.isChecked()) { hobbies.append(阅读 ); } if (cbMusic.isChecked()) { hobbies.append(音乐 ); } // 校验 if (name.isEmpty()) { Toast.makeText(MainActivity.this, 姓名不能为空, Toast.LENGTH_SHORT).show(); return; } if (!age.matches(\\d)) { Toast.makeText(MainActivity.this, 年龄必须为数字, Toast.LENGTH_SHORT).show(); return; } if (phone.length() ! 11) { Toast.makeText(MainActivity.this, 手机号应为11位, Toast.LENGTH_SHORT).show(); return; } User user new User(name, age, gender, phone, hobbies.toString().trim()); Intent intent new Intent(MainActivity.this, ResultActivity.class); intent.putExtra(user, user); startActivity(intent); } });几个细节说明一下。getText().toString().trim()里我把trim加上了目的是去掉用户误输入的首尾空格。如果忘了trim用户输入“张三 ”和“张三”会当成两个不同的数据在后续做匹配或展示时容易出现莫名其妙的bug。年龄校验用正则\\d判断是否为纯数字。也可以用Integer.parseInt加try-catch二选一即可。正则写法更简洁但要注意在Java字符串里反斜杠要写成\\d。手机号校验只做了长度判断没有判断号段。对于入门项目先别搞太复杂后面学了正则表达式再优化也不迟。3.3 接收页(ResultActivity)展示数据第二个Activity的布局很简单几个TextView从上到下排列用来展示个人信息。关键在onCreate里取Intent中的数据User user (User) getIntent().getSerializableExtra(user); if (user ! null) { TextView tvName findViewById(R.id.tv_name); tvName.setText(姓名 user.getName()); // 其他字段同理 }要注意取对象的时候如果Intent里没传对应keygetSerializableExtra会返回null所以先用if判空避免空指针。在开发中这类“接收方”的数据判断很重要尤其是后面数据来源多了以后不判空很容易闪退。3.4 如果想展示多条注册记录用List RecyclerView作业要求如果更进一步要求展示“所有注册过的用户”这时候Intent传单条数据就不够用了。无数据库版最直接的办法是搞一个静态List把User对象加进去再用RecyclerView展示。单例或静态List的写法很简单比如建一个DataHolder类public class DataHolder { public static ListUser userList new ArrayList(); }注册按钮点击时DataHolder.userList.add(user);然后跳到列表页用RecyclerView展示。这套思路不涉及数据库但能很好地模拟“多条记录展示”的效果。因为数据在静态变量里所以只要应用进程还活着切到别的页面再回来数据都不会丢。但注意应用被系统杀掉或者手动划掉之后静态List就清空了。这一点在演示时最好提前说明避免被误认为“存在数据库里”。RecyclerView的Adapter代码比较固定核心是继承RecyclerView.Adapter重写onCreateViewHolder和onBindViewHolder。示例里我建一个UserAdapterpublic class UserAdapter extends RecyclerView.AdapterUserAdapter.UserViewHolder { private ListUser userList; public UserAdapter(ListUser userList) { this.userList userList; } Override public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_user, parent, false); return new UserViewHolder(view); } Override public void onBindViewHolder(UserViewHolder holder, int position) { User user userList.get(position); holder.tvName.setText(user.getName()); holder.tvPhone.setText(user.getPhone()); } Override public int getItemCount() { return userList null ? 0 : userList.size(); } class UserViewHolder extends RecyclerView.ViewHolder { TextView tvName, tvPhone; public UserViewHolder(View itemView) { super(itemView); tvName itemView.findViewById(R.id.tv_name); tvPhone itemView.findViewById(R.id.tv_phone); } } }列表页初始化时用LinearLayoutManager设置RecyclerView的排列方向再把adapter set进去RecyclerView recyclerView findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(new UserAdapter(DataHolder.userList));学到这里“无数据库版多用户注册”就能完整跑通了。从单条展示升级到列表展示时整个改造的量的确不大说明这个方案足够贴合学习场景。4. 常见问题排查与避坑指南4.1 点击注册没反应按钮监听没生效新手最常见的问题代码写了setOnClickListener但点了按钮毫无反应。排查思路一般是先看按钮id是否和布局里一致然后看onCreate里是否在setContentView之后才findViewById。还有一种情况是按钮被其它布局遮挡点了根本没点到按钮上。这种问题用模拟器不常见但真机调试时如果自定义了主题或加了浮动控件可能发生。建议在点击事件回调里先打一行Log确认到底有没有进入监听。Log.d(Register, 按钮被点击了);如果Log有输出但后续逻辑没走那就是某个控件获取值时报了异常或者是校验条件把流程提前return了。把校验那段代码注释掉再试很容易定位。4.2 EditText 获取不到值getText()返回空这里有个常见的低级错误把etName.getText()直接当成String用结果编译不过或者拿到的是Editable对象转字符串时忘了调用toString。另外如果Activity里存在多个同id的控件或者布局里id写重复了findViewById拿到的可能不是你想的那个输入框。还有一个隐蔽点如果你在布局文件里给EditText设置了android:text默认值用户没有修改直接点注册取到的就是默认值。这在调试阶段容易造成“我什么都没填也能注册成功”的错觉。用TextUtils.isEmpty()去判断时要注意默认值不是空字符串所以校验不会拦截。4.3 RadioGroup 没选中项导致的空指针获取性别时getCheckedRadioButtonId()返回-1表示没选中。如果你不判-1直接findViewById(-1)就会抛异常。建议在UI上提前处理给RadioGroup加一个默认选中项rbMale.setChecked(true)这样用户不选也有值。如果产品需求要求用户必须手动选择那就保留校验提示不要默认选中。判断选中项还有另一种写法给RadioGroup设置setOnCheckedChangeListener在回调里记录当前选中的文字。这种写法适合“选中后马上联动展示”的场景单纯最后读取用onClick里的getCheckedRadioButtonId就够了。4.4 CheckBox 状态拼接多了一个空格多个CheckBox拼接爱好时用StringBuilder逐项append最后trim一下去掉末尾空格。如果不trim展示的时候“阅读 音乐 ”末尾会多一个空格虽然不影响功能但界面看起来不整洁。另外如果CheckBox初始是选中状态你需要在布局或代码里做处理。我建议全部默认不选中让用户显式选择这样数据含义更清晰。4.5 Intent传值后Receive页面数据为空数据为空通常是三个原因一是key写错了putExtra和getSerializableExtra用的字符串不一致二是对象没有实现Serializable导致运行时ClassCastException但如果你用getSerializableExtra(null)兜底可能掩盖了这个问题三是Activity启动时用错了Intent构造。我调试时经常用Log或Debug模式看一下传入的Bundle是否包含user这个keyBundle bundle getIntent().getExtras(); if (bundle ! null bundle.containsKey(user)) { User user (User) bundle.getSerializable(user); }这样写比直接getSerializableExtra更健壮至少不会因为key缺失直接崩。4.6 新Activity启动后闪退忘记在Manifest注册这是个特别容易犯的低级错误。在AndroidManifest.xml中所有Activity都要用activity节点注册否则启动时会直接抛ActivityNotFoundException。Android Studio有时会自动提示注册但手写Intent跳转时不一定会帮你补。每次新建Activity我建议顺手就去Manifest里检查一下别等运行报错了再回头找。报错信息里其实写得很清楚Unable to find explicit activity class看到这句话第一反应就是Manifest没注册。4.7 RecyclerView 数据没刷新往静态List里添加了数据切回列表页却发现新数据没显示。原因通常是列表页已经创建过一次RecyclerView还停留在原来的Adapter状态。解决方法是在onResume里重新设置adapter或者给adapter增加notifyDataSetChanged调用。简单做法是每次都重新setAdapter这在数据量小时没有性能问题Override protected void onResume() { super.onResume(); adapter new UserAdapter(DataHolder.userList); recyclerView.setAdapter(adapter); }如果希望更高端一点可以学习DiffUtil的用法但入门阶段手动notifyDataSetChanged就够了。5. 个人经验谈这个无数据库版项目还能怎么扩展5.1 先跑通流程再决定要不要数据库完成上面的代码之后整个注册和展示流程就通了。很多同学会问这个项目没有数据库是不是显得太low我的理解恰恰相反“无数据库版”不是偷懒而是用一种成本最低的方式把Android的界面和交互链路学会了。数据持久化是一个独立知识点如果非要在第一个项目里同时学出了问题你都分不清是Activity的问题还是数据库的问题。5.2 我自己踩过的一个坑我之前带过一个学生他照着教程写代码注册完也想展示多用户列表但不知道静态List和Activity之间的关系结果每次从注册页跳回列表页都发现旧数据没了。原因很简单他用new ArrayList()创建了一个局部变量Activity销毁后这个变量跟着消失。改成静态List之后就正常了。这件事让我想明白一件事入门项目里数据存哪、活多久比用什么工具存更重要。理解了这个后面学SQLite无非是换一个“活得更久”的存储容器。5.3 后面可以接着做的小改造做完基础版后可以考虑按这个顺序去升级第一步把数据用SharedPreferences保存实现“退出应用后再打开注册信息还在”。第二步用SQLite或Room存多用户数据做一个简单的注册用户列表。第三步加上用户名重复检测注册时去数据库里查一遍。第四步如果有后端课程需求把注册数据提交到服务端接口。每一步都是在无数据库版基础上做增量改动不会推翻重来。这也是为什么我特别推荐用无数据库版起步它不是终点而是给后面的学习搭了一个脚手架。当你把基础链路理解透再往上加东西一切都会顺理成章。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门