Android基础教程 - 学习完成记录

视频学习教程

视频链接:2022 最新 Android 基础教程,从开发入门到项目实战,看它就够了,更新中_哔哩哔哩_bilibili

学习下来,有遇到很多问题,在 chatgpt、claude 和 Android Studio 插件通义千问的帮助下,一一解决。

目前还是有很多不懂的,虽然学了一遍,敲了一遍,但是 Android 体系还是太多,需要不断地学习。

Gitee 地址

代码均可以跑通,视频中项目实战均实现。
Magnolia/AndroidLearning
如果可以,帮点个小星星,谢谢~


下面是一些记录。

资源IDs 变成 non-final

Resource IDs will be non-final by default in Android Gradle Plugin version 8.0, avoid using them in switch case statements.

在 Android Gradle Plugin 8.0 中,资源 ID 默认变为 non-final,意思是它们不再是编译时常量,而是动态生成的。这是因为 Android 的资源 ID 现在默认使用了新的构建优化方式,使得每次构建时资源 ID 可能发生变化,从而减少了重编译时间,但也带来了以下变化:

解释 non-final

  • 原本的 final 行为:在 Android Gradle Plugin 8.0 之前,资源 ID(如 R.id.example_button)被编译成 final 常量(不可变的静态值),因此可以直接用于 switch 语句,因为编译器在编译时可以确定它们的值。
  • non-final 意味着动态生成:从 8.0 开始,资源 ID 不再是 final 的。它们的值在每次构建时可能会动态生成,无法在编译时确定。因此,在 switch 语句中使用这些非固定值会导致编译错误,因为 switch 语句要求常量。

影响和替代方案

由于资源 ID 变为 non-final,在 Android Gradle Plugin 8.0+ 中,不能在 switch 语句中使用它们。可以使用 if-else 结构来替代 switch

变量声明为 final

将变量声明为 final 有以下好处:

  • 不可变性:确保该变量在初始化后不能被修改,提高代码的安全性和可预测性。
  • 线程安全:在多线程环境中,final 变量可以避免多个线程同时修改同一个变量带来的问题。
  • 优化:编译器可以对 final 变量进行一些优化,提高性能。
private String mRequest = "你好,在吗?";
// 可以写成:
private final String mRequest = "你好,在吗?";

override 注解

@Override 注解在 Java 中用于表示一个方法是在重写父类或实现接口中的方法。使用 @Override 有以下几个好处:

  • 提高可读性:明确告知其他开发者这个方法是一个重写的方法。
  • 编译器检查:如果方法签名与父类或接口中的方法不匹配,编译器会报错,帮助开发者发现潜在的错误。

如果不加 @Override 注解,代码仍然可以正常编译和运行,但会有以下问题:

  • 缺乏明确性:其他开发者阅读代码时可能不清楚这个方法是否是重写的。
  • 潜在错误:如果方法签名写错了(例如拼写错误或参数类型不匹配),编译器不会报错,但方法不会被正确调用,导致难以调试的问题。

.9.png

在 Android 开发中,.9.png 是一种特殊的图片格式,称为 Nine-Patch (九宫格) 图片。这种格式的图片在 .png 图片基础上做了特殊处理,主要用于实现拉伸和缩放效果,适应不同尺寸的屏幕和控件。

特点与用途

  1. 灵活拉伸:Nine-Patch 图片可以指定哪些区域可被拉伸,哪些区域保持不变。这对于按钮、对话框背景等需要根据内容大小动态调整的控件非常有用。
  2. 边界标记:Nine-Patch 图片的边界上有一像素宽的黑色线条,Android 会根据这些标记确定哪些部分可以拉伸,哪些部分保持原样。具体来说:
    • 左侧和上侧边界:定义图片可以被拉伸的区域。
    • 右侧和下侧边界:定义内容显示区域。
  3. 高效适配:Nine-Patch 图片在适应不同分辨率和屏幕尺寸时,不会失真或模糊,提供较好的视觉效果。适合用于各种弹窗、输入框背景、气泡等需要拉伸的图形背景。

示例应用

  • 按钮背景、输入框背景、对话框背景等需要根据内容大小动态变化的 UI 元素。

创建方法

Nine-Patch 图片可以通过 Android Studio 的 Draw 9-Patch 工具制作,或直接在图片上手动添加一像素的黑色边界。Android 会根据这些边界像素的标记进行渲染处理。

Nine-Patch 图片通过简单的标记,能以更小的资源量适配不同屏幕,是一种高效的图片处理方式。

复合按钮

由复合按钮 CompoundButton 派生而来的控件包括:CheckBoxRadioButtonSwitch

导入 Nullable

import androidx.annotation.Nullable;

作用是导入 Nullable 注解。这个注解来自 AndroidX 库,用于标记方法参数、返回值或字段,表示它们可以为 null

  • 代码可读性:提高代码的可读性和维护性,明确指出某个变量或参数可以为 null
  • 静态分析:帮助 IDE 和静态代码分析工具进行更准确的检查,减少潜在的空指针异常。

示例

@Nullable
public String getName() {return name;
}

在这个示例中,@Nullable 注解表明 getName 方法的返回值可以为 null

Boolean 与 boolean

Boolean married = ck_married.isChecked(); 
boolean married = ck_married.isChecked(); 这两种写法有什么区别?
  1. Boolean married = ck_married.isChecked();

    • 类型Booleanboolean 的包装类。
    • :可以为 truefalsenull
    • 使用场景:适用于需要表示 null 值的情况,例如在集合中存储布尔值或处理可能为 null 的返回值。
  2. boolean married = ck_married.isChecked();

    • 类型boolean 是基本数据类型。
    • :只能为 truefalse
    • 使用场景:适用于不需要表示 null 值的情况,性能更好,占用内存更少。

在代码中:

  • Boolean married = ck_married.isChecked();:这里 married 变量可以为 truefalsenull。但由于 isChecked() 方法总是返回 truefalse,所以 married 不会为 null
  • boolean married = ck_married.isChecked();:这里 married 变量只能为 truefalse,更符合实际需求,因为 isChecked() 方法不会返回 null

推荐做法

在大多数情况下,特别是当你确定变量不会为 null 时,推荐使用基本数据类型 boolean,因为它更高效且占用内存更少。

boolean married = ck_married.isChecked();

总结

  • Boolean:包装类,可以为 null
  • boolean:基本数据类型,不能为 null
  • 推荐:在不需要表示 null 值的情况下,使用 boolean

参数化查询和静态查询

参数化查询

String sql = "select * from " + TABLE_NAME + " where phone=? and remember=1";
Cursor cursor = mRDB.rawQuery(sql, new String[]{phone});
  1. SQL 查询:

    • select * from <TABLE_NAME> where phone=? and remember=1:这条 SQL 语句从表中选择所有列,条件是 phone 等于某个值且 remember 等于 1。
    • ? 是一个占位符,用于防止 SQL 注入攻击。
  2. 参数化查询:

    • new String[]{phone}:这是一个字符串数组,包含一个元素 phone。这个数组中的值会替换 SQL 语句中的 ? 占位符。
    • 例如,如果 phone 的值是 "1234567890",那么最终的 SQL 语句会变成 select * from <TABLE_NAME> where phone='1234567890' and remember=1

静态查询

String sql = "select * from " + TABLE_NAME + " where remember=1 order by _id desc limit 1";
Cursor cursor = mRDB.rawQuery(sql, null);
  1. SQL 查询:

    • select * from <TABLE_NAME> where remember=1 order by _id desc limit 1:这条 SQL 语句从表中选择所有列,条件是 remember 等于 1,并按 _id 列降序排列,只取第一行。
    • 没有使用占位符 ?,因为查询条件中没有动态参数。
  2. 参数化查询:

    • null:表示没有参数需要传递给 SQL 语句。

为什么前者多了 new String[]{phone}

  • 参数化查询:new String[]{phone} 用于传递动态参数 phone 给 SQL 语句中的占位符 ?。这样做可以防止 SQL 注入攻击,提高安全性。
  • 静态查询:第二段代码没有动态参数,因此不需要传递参数数组,直接使用 null 即可。

总结

  • 第一段代码:使用参数化查询,动态传递 phone 参数。
  • 第二段代码:使用静态查询,没有动态参数。

android.intent.action.VIEW

"android.intent.action.VIEW" 或者 "android.intent.action.ACTION_VIEW" 都可以

Intent intent = new Intent(Intent.ACTION_VIEW);
<activityandroid:name=".ThirdActivity"android:exported="false"tools:ignore="AppLinkUrlError"><intent-filter><action android:name="android.intent.action.ACTION_VIEW" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="http" /></intent-filter>
</activity>

简要解释原因

在 Android 中,Intentaction 属性用于指定操作类型。"android.intent.action.VIEW""android.intent.action.ACTION_VIEW" 实际上是同一个常量的不同表示形式。

  • "android.intent.action.VIEW":这是直接使用字符串形式的 action 名称。
  • "android.intent.action.ACTION_VIEW":这是通过 Intent 类中的静态常量 Intent.ACTION_VIEW 来引用的。

这两种方式在功能上是等价的,因为它们都指向同一个标准的 Android 操作名称 "android.intent.action.VIEW"

分点描述

  • 字符串形式 vs 常量形式

    • 使用字符串形式(如 "android.intent.action.VIEW")时,代码更直观,但容易出现拼写错误。
    • 使用常量形式(如 Intent.ACTION_VIEW)时,代码更安全,编译器可以进行类型检查和自动补全,减少错误。
  • 推荐使用常量形式

    • 使用常量形式可以提高代码的可读性和维护性。
    • 编译器可以在编译时检查常量的有效性,避免运行时错误。

示例代码

AndroidManifest.xml 中使用常量形式

<activityandroid:name=".ThirdActivity"android:exported="false"tools:ignore="AppLinkUrlError"><intent-filter><action android:name="android.intent.action.VIEW" /><!-- 或者使用 --><action android:name="android.intent.action.ACTION_VIEW" /><category android:name="android.intent.category.DEFAULT" /><data android:scheme="http" /></intent-filter>
</activity>

在 Java 代码中使用常量形式

else if (v.getId() == R.id.btn_jump2web) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.setData(Uri.parse("http://www.baidu.com"));startActivity(intent);
}

虽然 "android.intent.action.VIEW""android.intent.action.ACTION_VIEW" 都可以正常工作,但建议使用常量形式 Intent.ACTION_VIEW,以提高代码的安全性和可维护性。


Bug记录

购物车数目只更新一次
    private void addToCart(int goodsId, String goodsName) {int goodsCount = MyApplication.getInstance().goodsCount;++goodsCount;tv_count.setText(String.valueOf(goodsCount));mDBHelper.insertCardInfo(goodsId);ToastUtil.show(this, "已添加一件" + goodsName + "到购物车");}

原因:仅对局部变量 goodsCount 进行自增操作,此时MyApplication.getInstance().goodsCount的值并没有被修改,首次操作时, goodsCount 加一了,所以购物车数目会加一。但是,后面再添加就不会更新,因为每次获取的 goodsCount 都是一样的值,tv_count 更新也都是第一次更新的数字。

先对MyApplication.getInstance().goodsCount进行自增操作,然后将自增后的结果赋值给goodsCount,确保MyApplication.getInstance().goodsCount 和UI显示同步更新。

    private void addToCart(int goodsId, String goodsName) {int goodsCount = ++MyApplication.getInstance().goodsCount;tv_count.setText(String.valueOf(goodsCount));mDBHelper.insertCardInfo(goodsId);ToastUtil.show(this, "已添加一件" + goodsName + "到购物车");}

问题处理

Run后模拟器未启动app

可能的原因或者解决方法

  • 模拟器是否多开,在另一个中启动

  • 重启模拟器,清除模拟器数据(wipe data)后重启

  • adb devices 查看状态

    如果是 unauthorized,尝试 adb kill-server, adb start-server,设置 cold boot 启动

  • 查看 AndroidManifest.xml 是否配置正确

模拟器进程被占用

AVD Pixel_2_API_31 is already running. If that is not the case, delete the files at D:\software\Android.android\avd/Pixel_2_API_31.avd/*.lock and try again.

taskkill /F /IM qemu-system-* /IM emulator-* /IM adb.exe
del /F /Q D:\software\Android\.android\avd\Pixel_2_API_31.avd\*.lock

使用 procexp.exe 找到并结束进程。


记录

AndroidStudio 中, debug 运行代码,生成包 build/intermediates/apk/debug/chapter06-debug.apk

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web开发-JavaEE应用原生和FastJson反序列化URLDNS链JDBC链Gadget手搓

知识点&#xff1a; 1、安全开发-JavaEE-原生序列化-URLDNS链分析 2、安全开发-JavaEE-FastJson-JdbcRowSetImpl链分析 利用链也叫"gadget chains"&#xff0c;我们通常称为gadget&#xff1a; 1、共同条件&#xff1a;实现Serializable或者Externalizable接口&…

OpenCV操作函数

1、cv2.imread&#xff08;&#xff09; 2、 cv2.imshow&#xff08;&#xff09; 3、 cv2.waitKey&#xff08;&#xff09; 4、cv2.imwrite&#xff08;&#xff09; 5、cv2.selectROI&#xff08;&#xff09; 6、 cv2.VideoCapture() 7、cv2.cvtColor&#xff08;&#xff…

AI编程新纪元:GitHub Copilot、CodeGeeX与VS2022的联合开发实践

引言:AI编程时代的到来 在软件开发领域,我们正站在一个历史性的转折点上。GitHub Copilot、CodeGeeX等AI编程助手的出现,结合Visual Studio 2022的强大功能,正在重塑代码编写的本质。这不仅是工具层面的革新,更是开发范式的根本转变。能够有效利用这些AI工具的开发者将跨…

[特殊字符] MySQL MCP 开发实战:打造智能数据库操作助手

&#x1f4a1; 简介&#xff1a;本文详细介绍如何利用MCP&#xff08;Model-Control-Panel&#xff09;框架开发MySQL数据库操作工具&#xff0c;使AI助手能够直接执行数据库操作。 &#x1f4da; 目录 引言MCP框架简介项目架构设计开发环境搭建核心代码实现错误处理策略运行和…

Dify部署过程中的错误和解决方案汇总

本文仅限于记录Dify部署及使用过程中的BUG和解决方案 1. Dify配置SearXNG时报错&#xff1a; 报错内容&#xff1a; PluginInvokeError: {"args":{},"error_type":"ToolProviderCredentialValidationError","message":"Error 4…

C#中async await异步关键字用法和异步的底层原理

目录 C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结 C#异步编程 一、异步编程基础 异步编程是啥玩意儿 就是让程序在干等着某些耗时操作&#xff08;比如等网络响应、读写文件啥的&#xff09;的时候&#xff0c;能把线程腾出来…

安全教育知识竞赛答题小程序怎么做

以下是制作安全教育知识竞赛答题小程序的一般步骤&#xff1a; 一、准备阶段 注册小程序账号&#xff1a;前往微信公众平台&#xff0c;注册一个小程序账号&#xff0c;主体类型可根据实际情况选择个人或企业等&#xff0c;注册成功后登录获取appid。 下载安装开发工具&#x…

记录待办事项的便签软件有没有推荐的?

在快节奏的现代生活中&#xff0c;我们每天都要处理大量的工作任务和生活琐事&#xff0c;稍有不慎就可能遗漏重要事项。你是否经常遇到这样的情况&#xff1a;明明记得有件事要做&#xff0c;却怎么也想不起来是什么&#xff1b;或者手头同时有好几项任务&#xff0c;却不知道…

实验四 中断实验

一、实验目的 掌握中断服务程序的编写。 二、实验电路 三、实验内容 1&#xff0e;实验用PC机内部的中断控制器8259A&#xff0c;中断源用TPC-ZK实验箱上的单脉冲电路&#xff0c;将单脉冲电路的输出接中断请求信号IRQ&#xff0c;每按一次单脉冲按键产生一次…

React 项目src文件结构

SCSS 组件库 SCSS为预处理器 支持除原生CSS外的其他语句 别名路径 在项目下的第一级目录就加入craco.config.js文件并且修改packpage.js 中的部分 // 扩展webpage的配置const path require(path)module.exports {// exports配置webpack:{// 配置别名alias:{:path.resolve(__d…

Cursor入门教程-JetBrains过度向

Cursor使用笔记 **前置&#xff1a;**之前博主使用的是JetBrains的IDE&#xff0c;VSCode使用比较少&#xff0c;所以会尽量朝着JetBrains的使用习惯及样式去调整。 一、设置语言为中文 如果刚上手Cursor&#xff0c;那么肯定对Cursor中的众多选项配置项不熟悉&#xff0c;这…

Linux上位机开发实践(SoC和MCU的差异)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 soc一般是指跑linux的芯片&#xff0c;而mcu默认是跑rtos的芯片&#xff0c;两者在基本原理方面其实差异不大。只不过&#xff0c;前者由于性能的原…

离线导出和安装Python库

详细介绍&#xff1a;离线导出和安装Python库 常用命令&#xff1a; 生成requirement.txt文件 pip freeze > requirement.txt离线批量下载库 pip download -d packages -r requirement.txt离线批量安装库 pip install --no-index --find-links./ -r requirement.txt

基于Vue Node.js的电影售票网站的设计与实现(源码+lw+部署文档+讲解),源码可白嫖!

摘要 互联网技术的成熟和普及&#xff0c;势必会给人们的生活方式带来不同程度的改变。越来越多的经营模式中都少不了线上运营&#xff0c;互联网正强力推动着社会和经济发展。国人对民族文化的自信和不同文化的包容&#xff0c;再加上电影行业的发展&#xff0c;如此繁荣吸引…

利用 Python 和 AI 技术创作独特的图像艺术作品

1. 项目目标 生成艺术作品&#xff1a;利用 AI 模型&#xff08;如 Stable Diffusion&#xff09;生成具有艺术风格的图像。自定义风格&#xff1a;通过文本提示&#xff08;prompt&#xff09;控制图像的艺术风格&#xff08;如赛博朋克、印象派、超现实主义等&#xff09;。…

XR技术赋能艺术展演|我的宇宙推动东方美学体验化

本次广州展览现场引入我的宇宙XR体验模块&#xff0c;通过空间计算与动作捕捉技术&#xff0c;让观众在潮玩艺术氛围中体验虚拟互动&#xff0c;打造“看得懂也玩得动”的展演新场景。 作为科技与文化融合的推动者&#xff0c;我的宇宙正在以“体验科技”为媒介&#xff0c;为潮…

接口的集成测试步骤

一、集成测试是什么 ‌接口的集成测试‌是指在软件开发过程中&#xff0c;将各个模块或组件按照设计要求组合在一起&#xff0c;并测试它们之间的接口是否能够正确交互和协同工作的过程。集成测试是软件开发中的一个重要阶段&#xff0c;通常在单元测试之后进行&#xff0c;目的…

上门服务 APP 30 亿营收商业模式在乌干达的技术赋能与实践

不久前&#xff0c;非洲乌干达出现黑人女技师提供上门足疗服务的消息引发关注。据了解&#xff0c;当地一次40分钟的上门按摩服务仅需约40元人民币&#xff0c;价格仅为国内同类服务的十分之一。这一现象折射出全球健康服务行业正在经历的数字化转型浪潮。 国内领先的上门服务平…

go语言学习笔记:gin + gorm + mysql 用户增删改查案例入门

大家好&#xff0c;我是此林。 Golang 语言现在已经成为了编程的趋势&#xff0c;毕竟是大厂背书嘛&#xff0c;Google 研发的。 目前很多云原生项目都是基于 go 来编写的&#xff0c;比如&#xff1a; Kubernetes (K8s)​ 容器编排系统&#xff0c; Docker​ 容器化技术&…

探索亮数据Web Unlocker API:让谷歌学术网页科研数据 “触手可及”

本文目录 一、引言二、Web Unlocker API 功能亮点三、Web Unlocker API 实战1.配置网页解锁器2.定位相关数据3.编写代码 四、Web Scraper API技术亮点 五、SERP API技术亮点 六、总结 一、引言 网页数据宛如一座蕴藏着无限价值的宝库&#xff0c;无论是企业洞察市场动态、制定…