ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Android开发基础技能练习场:RYG分级实战训练指南

Android开发基础技能练习场:RYG分级实战训练指南 做Android开发这几年我一直有个感受网上教程铺天盖地但很多新人练完几个Demo到真要接项目时还是卡在“这个功能从哪下手”上。这个【RYG】Android开发基础技能练习场就是我专门搭给自己、也推荐给想系统打基础的人的一套训练体系。它不是又一个教程合集而是一组按“红黄绿”分级拆解后的实战练习项目围绕四大组件、UI布局、数据存储、网络与蓝牙、系统集成这些Android开发核心点一个一个过手。如果你正在自学Android开发或者工作两三年但总觉得基础不扎实这套练习场的思路和踩坑记录应该能帮上忙。1. 练习场整体设计与思路拆解1.1 RYG分级的由来把“会一点”变成“能交付”练习场的名字里RYG是Red、Yellow、Green三个等级的颜色标识它对应的是我在带人时习惯用的能力分层Red层基础概念能看懂跟着教程能敲出代码但不理解底层逻辑换个场景就懵。Yellow层能独立完成一个功能模块知道为什么要这么写遇到问题能定位到具体环节。Green层不仅能做出来还考虑性能、兼容性、可维护性代码拿出来可以直接进项目交付。我发现大部分自学者长期停留在Red层原因很简单练习方式太“线性”了。教材上教你写一个Activity你就写一个Activity教你用LiveData你就用LiveData。但真实项目里往往是Activity、Fragment、ViewModel、Room、Service混在一起交互技能点是网状的。所以这个练习场的第一步就是先把Android开发里的核心技能点拆出来编成一个可训练的清单然后每个练习都故意把几个技能点揉在一起逼着你跳出“单点练习”的舒适区。1.2 从需求反推技能点清单怎么列才不过时有些读者可能会问Android技术更新那么快今天是View明天是Compose我今天列一个清单是不是很快就过期了我的回答是清单会过期但拆解的方法不会。我列技能点的方式是“从真实功能反推”。比如我想做一个“带图片的本地笔记App”那至少要拆出这些技能点界面层列表页、编辑页的布局设计RecyclerView的Adapter和ViewHolder怎么写数据层笔记的增删改查用什么存储方案SQLite、Room还是直接操作文件文件管理图片存在哪应用私有目录还是公共媒体目录Android 10以后的分区存储怎么适配组件通信编辑完返回列表怎么刷新用startActivityForResult还是ViewModel共享数据系统集成需要拍照选图时怎么调起相机或相册FileProvider怎么配运行时权限怎么申请。你会发现这些技能点跟“用View还是Compose”基本无关它背后是Android系统的稳定骨架。所以这个练习场把骨架上的节点一个个过掉你在外面单独学某个UI框架的新写法也能很自然地挂在这张网上。1.3 训练路线图分五个阶段滚动推进RYG练习场我实际执行时分了五个阶段每个阶段侧重点不同但都会有意保留上一阶段的技能点作为“复习负担”。阶段一环境与工具链能跑通一个App到真机/模拟器上阶段二界面与交互把静态页面做漂亮把页面跳转和生命周期理顺阶段三数据与存储本地持久化、跨页面共享、文件读写阶段四系统能力与硬件相机相册、蓝牙、传感器、多媒体等阶段五工程化与优化模块化、性能分析、打包发布阶段切分不是死规矩我自己练的时候经常来回跳。比如阶段三做数据存储发现列表页卡顿又回阶段二去复习RecyclerView的复用机制。这种“回炉”其实特别重要它才是把Red层变成Yellow层的过程。2. 环境与工具链搭建别让版本问题卡住练习进度2.1 Android Studio版本选择不需要追新但要能对齐练习场开工前最重要的事就是把开发环境弄利索。很多新手在Android Studio下载和SDK配置上就会卡一两天倒不是难是版本组合太乱了。我自己的经验是不要一上来就追最新版但也不要停在特别老的版本上。最近有位朋友问我Android Studio Hedgehog2023.1.1 Patch 2能不能支持AGP 8版本。答案是支持Hedgehog这个版本内置的默认AGP版本就是8.1.x完美适配。这里的关键点是你新建项目时Android Studio会按默认模板给你配好一套Gradle和AGP版本但如果你从网上拷贝了一个老项目的build.gradle文件很可能会出现AGP版本要求Gradle最低版本、但本地Gradle版本太低的情况。AGP 8.0要求Gradle 8.0以上JDK 17AGP 7.4要求Gradle 7.5以上JDK 11AGP 4.x系列则对应更老的Gradle。这套对应关系不复杂但很烦。我的做法是项目里有一个gradle-wrapper.properties文件里面写死了Gradle版本改项目时优先保证它跟AGP匹配再来处理其他问题。Android Studio官网其实有一个版本兼容表我不止一次建议大家直接翻那张表比记什么教程靠谱得多。2.2 SDK、模拟器和真机调试的前期准备SDK放在哪个目录这个问题在热词搜索里都有人问。Windows上默认路径是C:\Users\你的用户名\AppData\Local\Android\SdkmacOS是~/Library/Android/sdk。如果你下载了Android SDK官网的压缩包自己解压到任意路径也可以只要在Android Studio里设置好SDK Location路径就行。模拟器方面纯练习UI和基础组件的话模拟器完全够用。但凡是涉及蓝牙、摄像头、传感器这种硬件功能模拟器支持很差建议直接准备一台真机。真机调试需要开“开发者选项”每个品牌大同小异一般是连续点七次“版本号”就能调出来。这里要注意Android 11以后的无线调试功能手机和电脑连同一个Wi-FiAndroid Studio里选“Pair using Wi-Fi”扫码配对不用插线也能调试比传统方式方便不少。2.3 Gradle配置的几个“作业级”知识点环境搭建的最后一步是理解Gradle配置。其实新手不需要学Gradle把Java和Groovy学透但两个文件的作用要搞清楚根目录的settings.gradle声明项目包含哪些模块以及依赖仓库地址模块目录的build.gradle声明这个模块的SDK版本、依赖库、打包配置。练习场里我要求自己把每个依赖都手动加到build.gradle里而不是直接复制网上配置。因为等你做完四五个练习你会发现把implementation写错成api、或者用compile这种老写法会导致很不直观的编译错误。理解依赖作用域implementation、api、annotationProcessor虽然烦但它直接影响你的组件化能力是Green层必须掌握的技能。3. 核心练习模块拆解与实操要点3.1 四大组件不只是会跳页面要清楚它们的职责边界Android开发的基础核心永远绕不开Activity、Service、BroadcastReceiver、ContentProvider这四大组件。RYG练习场里我把它们当做一个“家庭系统”来理解Activity是门面负责接待用户Service是后勤在后台干活BroadcastReceiver是消息系统有事情广播通知ContentProvider是文件柜对外提供数据访问入口。练习的时候最容易出问题的是生命周期。Activity的onCreate、onStart、onResume、onPause、onStop、onDestroy这一套我建议你写日志打点然后切换后台、旋转屏幕、按Home键每一步都记录生命周期回调顺序。这个练习看着简单但对理解状态的保存和恢复特别重要。我实际踩过的坑是旋转屏幕后Activity重建界面上输入框的内容全丢了。解决办法是在onSaveInstanceState里保存数据或者在Manifest里给Activity配置android:configChanges但后者不是万能药用了反而可能引发布局适配问题。Service这边要重点理解Android 8.0以后的后台限制。从Android 8.0开始应用在后台时不能随意创建后台Service需要使用startForegroundService配合前台服务通知不然系统直接抛IllegalStateException。我练的时候写了一个音乐播放器的Service花了整整一个晚上才把“通知栏常驻”和“后台播放”捋顺。BroadcastReceiver的坑主要在注册方式。动态注册要跟Activity/Fragment生命周期绑定在onPause或onStop里反注册不然容易内存泄漏静态注册可以用来监听系统广播但Android 8.0以后很多隐式广播都限制了接收不到是常态需要想替代方案。ContentProvider和FileProvider是练习场里偏怪的一个点。日常开发里直接写ContentProvider的机会不多但了解它的机制对理解跨应用数据共享和文件分享都有帮助。比如热词里经常出现content://com.baidu.searchbox.fileprovider/baiddpath/android/data/com.ba这类路径它就是某些应用通过FileProvider暴露的文件访问地址。在练习时我手动创建过一个自己的FileProvider配置好file_paths.xml实现App之间安全地分享一张图片做完才发现平时很多“分享到微信/QQ”的场景底层就有这一环。3.2 UI与自定义View从“能看”到“用得顺手”界面练习占了整个练习场非常大的比重。毕竟用户第一眼看到的就是UI。我练的第一个重点是把常用的布局写熟LinearLayout的权重、RelativeLayout的约束、ConstraintLayout的复杂嵌套关系。这里要特别提醒ConstraintLayout现在虽然不是唯一选择但它能极大降低布局嵌套层级对性能有实际帮助。练习的时候可以故意用ConstraintLayout去还原一个网易云音乐或者微博的首页UI这个过程能学到很多细节。热词里提到“协调布局Banner”这是不少App首页的经典组合。CoordinatorLayout配合AppBarLayout、CollapsingToolbarLayout可以实现“上滑时标题栏折叠下滑时展开”的效果配合Banner轮播图表面看着简单实际做的时候要注意嵌套滑动机制和事件冲突。比如Banner在竖直方向上不能正常滑动通常就是RecyclerView和ViewPager2的事件拦截没有处理好。这个问题的排查思路一般是先确认父容器有没有requestDisallowInterceptTouchEvent再确认子View的onInterceptTouchEvent返回值。自定义View是很多人的心理障碍。我给的练习建议是分三步走第一步只复写onDraw画圆、画线、画文字第二步重写onMeasure理解wrap_content为什么需要自己处理EXACTLY、AT_MOST、UNSPECIFIED三种模式怎么区分第三步处理触摸事件做一个可以随手势移动的红点。整个过程下来你对View的测量、布局、绘制流程会有真正的体感而不是背概念。还有热词里提到的“Android动态图标主题”这个是Launcher层面的知识。普通应用图标是静态的Android 13以后支持主题图标也就是根据系统深浅色模式自动切图标样式。练习一下这个能让应用看起来更“现代”但它本质是资源适配问题把图标做成Adaptive Icon在mipmap目录下配置前景和背景。3.3 数据存储本地持久化不是只有SQLite一条路数据存储练习是很多人的弱项因为平时教程大多停留在“用SharedPreferences存一个登录状态”的级别。但实际项目里数据结构复杂得多。RYG练习场里我要求自己用三种方式分别实现同一个需求保存一组“待办事项”。第一版用SharedPreferences把整个List序列化成JSON字符串靠Gson塞进去。好处是快坏处是数据量大了没法按条件查询第二版用SQLite但不引入ORM手工写SQL建表、增删改查练一遍SQLiteOpenHelper。这个过程能让你理解SQL语句和事务第三版用Room定义Entity、Dao、Database写完后对比第二版你会发现Room不用写太多模板代码还能用协程和Flow做观察。但它的底层仍然和SQLite密不可分理解第二版才能理解Room的“坑”。图片文件处理方面Android 10以后的分区存储是个大坑。老代码直接拿文件绝对路径去读图片在新的系统上很容易读不到。正确姿势是把图片写到应用专属目录getExternalFilesDir()或者通过MediaStore写入公共媒体目录。练习时我特意做了个“复制文件”功能从系统相册选一张图复制到应用缓存目录再显示出来。这个练习同时覆盖了SAFStorage Access Framework、文件读写、ContentResolver、URI权限等好几个知识点。在热词搜索里能看到有人直接写file:///storage/emulated/0/android/data/...这样的路径这是很老的写法在Android 7.0以后用FileProvider之前一般不会直接暴露真实路径所以我强烈建议不要在代码里拼这种物理路径。3.4 网络与蓝牙联调才是重头戏网络请求是App的刚需。练习时我用OkHttp Retrofit做了几轮先是不接任何封装直接用HttpURLConnection请求一个公开接口把JSON字符串打印出来然后换成OkHttp理解拦截器怎么加日志最后用Retrofit把接口定义成注解方法。每一步都亲手配置一遍之后你看到报错日志就大概知道是哪一层出的问题。Android蓝牙这块在练习场里我单独开了一个模块。蓝牙经典和BLE两套API差异很大。经典蓝牙面向音频和文件传输需要ACCESS_FINE_LOCATION权限老版本还需要BLUETOOTH和BLUETOOTH_ADMINBLE扫描在Android 12以后引入了BLUETOOTH_SCAN和BLUETOOTH_CONNECT用旧的申请方式会闪退。我练习时做了一个BLE扫描器扫描附近的低功耗蓝牙设备显示设备名和信号强度RSSI。这里最折腾的是权限适配不同Android版本对定位权限的要求不一样。一个经验是先把targetSdkVersion降低到28跑通扫描再逐步升到最新观察每一步需要补什么权限这个过程比直接看文档记得牢。3.5 自动化构建、性能调优与特殊调试场景除了常规功能开发练习场还有一个很重要的部分学会自己调性能。热词里提到的“android studio 火焰图 指南”其实就是Profiler里的CPU性能分析。在Android Studio的Profiler面板里用“Call Stack”或“Flame Chart”视图可以直接看到哪个函数占用CPU最长。练这个性能分析时我故意在onCreate里写了一段死循环逻辑然后用火焰图查找瞬间就把问题定位到具体类和方法了。这个能力在优化启动速度和列表滑动流畅度时特别有用。还有一个特殊场景是嵌入式相关调试。热词里有“i2c-tools 在 android 上使用”和“android openocd”这类需求大多出现在做驱动开发或底层的场景。如果你的练习场是纯应用开发可以先跳过。但如果你跟我一样做过Linux或单片机的交叉编译会发现在Android上用i2c-tools需要先确认设备有没有root然后把工具通过adb push推到/data/local/tmp下加上执行权限再用。这一套思路跟应用开发的技术栈不是一回事属于另外一个方向练习场里作为“扩展知识”看看即可。4. 实操过程从零做一个“本地技术笔记App”4.1 需求拆解三天时间给自己设定一个完整项目理论说了一堆不如动手来一个完整的项目。我在练习场中后期给自己定的课题是用一套MVP版本的“本地技术笔记App”来收尾把前面练的所有技能点串起来。需求很简单但也不要小看应用启动进入笔记列表页按更新时间倒序展示点击加号新建笔记标题和内容都可以编辑支持给笔记插入一张图片从相册选择或拍照编辑完成保存列表立刻刷新支持长按删除删除前弹确认框技术选型我当时定为Kotlin JetpackViewModel、LiveData、Room RecyclerView 原生相机相册调用。没有用任何第三方图片加载库因为这个练习的目标是理解底层而不是学会调用Glide。4.2 一步步实现从页面框架到数据落地的完整链路第一步新建项目。包名我用com.ryg.notes主题用Material3。接着在build.gradle里配置好Room相关依赖包括room-runtime、room-ktx和kapt编译器插件。这里如果忘了配Kapt插件编译会直接报错找不到Room生成的代码。第二步搭页面骨架。列表页用一个RecyclerViewitem布局是一行标题加一行时间。编辑器页面用EditText和ImageView。跳转这里我不建议用简单的Adapter内直接startActivity而是用ViewModel LiveData做一个共享数据比如把点击事件通过Adapter的接口回调给ActivityActivity再决定跳转。这看起来多写了几行代码但它是“事件从View层流向业务层”的正规写法后面的维护会舒服很多。第三步实现数据层。定义NoteEntityid、title、content、imagePath、updateTime写NoteDao提供getAllNotes()、insert()、update()、delete()几个方法。Room的数据库类用单例模式创建。这里有个细节字段命名最好跟数据库列名一致或显式加ColumnInfo注解不然手滑改个变量名数据库就会神秘地出现“column not found”错误。第四步配置文件。相册选图和拍照都需要依赖FileProvider。在AndroidManifest.xml里添加provider节点配置authorities为${applicationId}.fileprovider然后在res/xml/file_paths.xml里声明可选路径。相册的图片我会存到应用外部缓存目录getExternalCacheDir()下的images文件夹这样不用申请存储权限也是官方推荐的做法。拍照则通过FileProvider.getUriForFile()生成URI传给相机App。第五步编辑保存后的刷新。这里最容易出问题。如果列表页通过startActivityForResult跳转编辑页返回时要重查一次数据库或者直接靠LiveData的观察者自动刷新。我用的是后者Activity在onCreate里observeViewModel里的notesRoom返回LiveDataListNoteEntity只要数据库有变化列表自动更新。这个体验很顺滑因为LiveData是在主线程回调更新UI安全。第六步长按删除加确认弹窗。用AlertDialog就可以删除后Room的LiveData会自动刷新列表。这一步没啥技术含量但它是交互细节的完整度问题MVP项目也需要有。4.3 调试与优化跑通功能只是开始接下来才是真功夫写完功能之后我用Android Studio的Profiler做了几个检查。第一项是启动耗时看MainActivity从创建到可交互的时间。第二项是内存占用重点做了一次页面反复进出后的堆内存变化看有没有内存泄漏。第三项是布局复杂度用Layout Inspector看列表页的视图层级。这个项目简单问题不大但这一套流程跑下来比我上十节理论课都有用。还有一个不太起眼但很关键的优化列表滑动时的卡顿。我故意在onBindViewHolder里加载图片时用了BitmapFactory.decodeFile很自然会卡。这也是我故意不引入图片加载库的原因。优化办法是加一层LruCache缓存再对图片做压缩采样。处理完这两步你再看Glide这类库的源码就很容易理解它内部到底在忙什么了。5. 常见问题与排查技巧实录5.1 版本与依赖冲突类问题练习场里最烦人的一批问题都跟版本有关。我把高频问题整理成了一张表方便你直接对照现象大概率原因处理方法Gradle同步报错Could not find com.android.tools.build:gradle依赖仓库没有配全或网络问题在settings.gradle里确认google()、mavenCentral()仓库存在必要时配置国内镜像编译报错Unsupported class file major versionJDK版本与AGP不匹配AGP 8.x用JDK 17AGP 7.x用JDK 11统一在File Project Structure里设置报错Duplicate class多个依赖库引入了相同类用./gradlew adependencies查看依赖树用exclude排除重复依赖Kotlin编译报错This version of Kotlin only supports...Kotlin插件版本与Android Studio内置Kotlin版本不匹配检查项目里build.gradle的Kotlin版本改成AS默认支持的稳定版本AAPT2报错file failed to compileres资源文件有非法字符或重复资源检查res目录下的文件名是否小写、是否命名合法检查values目录下有没有重复的字符串定义版本冲突我建议一定要亲自动手查一次依赖树命令是gradlew :app:dependencies虽然输出很长但它是理解“依赖传递”最直观的方式。很多新人遇到冲突就乱换版本号结果越换越乱实际上只要锁定某一个库的版本让其他依赖都使用该库的同一版本就能稳定解决大多数冲突。5.2 权限与真机适配类问题权限问题是练习场里踩坑最多的。比如Android 6.0以后危险权限必须在运行时动态申请Android 11以后部分机型上“读写外部存储”的授权逻辑又变了Android 12以后蓝牙权限又拆分了。这些规则如果只背不练换台老手机调试很容易翻车。我的建议是做一个权限申请的统一封装写一个PermissionManager里面封装checkPermission、requestPermission、onRequestPermissionsResult回调。所有需要权限的功能都走同一个入口判断是否授权、是否“不再询问”再弹设置页跳转。这套逻辑在任何项目里都能复用属于练习场里的“基础设施”。真机适配还有个老生常谈的问题UI在不同屏幕上的表现。HarmonyOS、小米、OPPO、vivo这些不同品牌ROM对后台管理、通知权限、电量优化都有各自的“深度管理”。做练习项目时尽量在2-3台不同品牌、不同Android版本的真机上跑一遍你会发现同样一段代码在老荣耀手机上Notification可能不弹在新小米手机上Service反复被杀。这些都不是你代码的错而是系统策略差异但你必须知道怎么应对。5.3 日志排查与调试技巧排查问题的基本功是看日志。Logcat里一堆红色报错新手容易慌。我的习惯是先找崩溃堆栈里第一个Caused by因为那才是真正的异常来源。比如一个常见的空指针崩溃崩溃堆栈可能显示的是MainActivity.java第75行但Caused by往往会明确指出是哪个对象为null。另一个高效手段是断点调试尤其是条件断点。在RecyclerView的Adapter里你不想每个item都停下来只想在position为3的时候停就可以在断点上设置条件为position 3这样调试效率极高。还有“Evaluate Expression”窗口你可以在断点处执行任意语句查看某个对象的内部状态这个是排查“为什么这个列表没有按预期过滤”的神器。5.4 几个你早晚会遇到的特殊问题除了上面的常见问题练习场进行到后期还会遇到一些“偏门”问题。这里我挑几个有代表性的说。第一个是打包时ProGuard混淆导致的运行时崩溃。你Debug版本跑得好好的一打Release包就崩十有八九是混淆规则没写好比如某个类名被混淆后反射找不到了。解决方法是导出一个完整崩溃堆栈用retrace.bat配合mapping.txt还原混淆前的类名和方法名。这个练习虽然有点老派但它能帮你真正理解“混淆”这件事。第二个是Android 10及以上系统对“后台启动Activity”的限制。有些App会通过后台任务拉起一个页面在某些ROM上会被系统拦截或者静默失败。如果遇到这种问题优先检查是否申请了SYSTEM_ALERT_WINDOW权限或者改用通知栏提醒而不是直接启动Activity。第三个是“android 14 root”这类搜索词背后代表的需求。我的建议是纯应用开发练习完全不需要root模拟器和真机调试足够了。如果你只是好奇Android底层可以学一下adb工具的使用很多系统信息都可以通过adb shell命令查看这比root安全得多也够用。6. 练习场日常怎么坚持训练和记录成长RYG练习场不是一次性的项目而是一个长期迭代的个人训练体系。我给自己定了一个规矩每个技能点练完写一篇简单的Markdown笔记记录“要解决的问题、实现步骤、踩坑、验证结果”。几个月下来它就成了我自己的“错题本”。第二次遇到类似问题时不用重新查一天资料翻一下笔记就能快速定位。在记录方式上我建议模板化。我自己的笔记模板是问题/需求是什么我第一方案的思路实际实现过程含关键代码和命令遇到的问题与排查过程最后沉淀出的经验还有一个实用习惯是建立自己的“代码片段库”。比如FileProvider的配置、Room数据库的搭建、动态权限申请、蓝牙扫描的权限适配这些都是高度模板化的代码每次重写浪费时间。我会把这些模板以代码片段的方式存下来新项目直接导入再改一改效率高很多。但要提醒一下模板只解决“重复劳动”你依然要搞懂每一行是什么意思不然模板一变运行环境你就只能干瞪眼。最后再分享一个练习技巧学会阅读官方文档而不是只搜博客。Android开发者官网对很多组件的解释和示例都在持续更新比如FileProvider、存储权限、蓝牙权限、前台服务限制这些内容以官方文档为准是最不容易过时的。搜索引擎的结果很多是两三年前的旧方案用在新项目上反而会引入新的问题。我一般流程是问题来了先搜关键词判断时间是否太旧再去官网确认最新API最后才动手改代码。做练习场这件事最大的收获不是我会了多少API而是养成了“知其所以然”的习惯。如果你也想稳扎稳打把Android基础打牢可以按这套思路去拆一个属于自己的练习项目一次只练一个点练完就记录日积月累你再回头看那些曾经让你头疼的功能会发现它们突然都变简单了。
返回列表