2. Android应用开发入门实践

1.前言

在上一章节,我们完成了安卓程序开发的环境搭建,从本节开始,我将带着大家从零开始一步一步开发出属于自己的安卓应用程序。

但要注意,我并不会真的完全从零基础开始一步一步给你介绍基本的语法细节,学习本系列教程之前,你至少需要会一门常见的语言,比如C/C++、python、java乃至前端的js。

比如正在开始写本教程的作者本人,截至目前写出这段文字时刻,我对将要使用的kotlin语言甚至都说不上会,只能说有点了解,写过hello world,仅此而已。

至于安卓App的开发,我更是在此前从来没有Android Studio这个开发环境开发过(仅仅使用过tauri框架自带的、将前端转为安卓App的功能)。

但这并不妨碍我写本系列教程,因为事实上各种语言、各种应用,本质上都是互通的,只不过换了个语法、规则,仅此而已。

而我又刚好写过大量的PC端应用程序、网站应用,了解常见的UI布局方式、软件底层运行原理,熟悉很多语言的语法规则及其本质。

所以在我看来,学习语言、框架都不要局限于某一类,当你见识的足够多时,就会逐渐触碰到本质,会发现一切大道均殊途同归,从而当你遇到一个新的框架、语言时,都不会有太多的波澜。

尤其是如今依然来到了大模型时代,如果遇到不会的,问一问deepseek就可以了,基本很快就能上手开发应用程序。

2.项目介绍

首先我们进入安装好的Android Studio程序,新建一个项目:

image.png

如果你没有新建过任何项目,那么你的上图界面和我长得并不一样,但依旧是点击“New Project”这个按钮,也就是新建项目。

然后来到下一步,选择手机、空项目,最后点击下一步:

image.png

从上面这个界面我们就能看出来,由于安卓系统运行在了各种设备上,所以实际上它并不仅仅是用来开发手机App的,比如第二个wear os实际上就是开发智能手环App的,第三个 Television则用来开发智能电视App的,最后一个automotive则是用来开发智能驾驶App的。

而这里选择的手机类别中的Empty Activity这个名字也很有讲究,前面Empty是空的意思,而Activity则是活动的意思,它为什么不叫空项目、而是叫空活动这样一个奇怪的名字呢?

这个会留到后续适当的时候对其进行介绍,这里就不展开了。

紧接着来到下一个创建项目的页面:

image.png

可以看到这里有很多选项,但实际上大部分都直接默认即可,只需要在第一个位置填上我们的App名称,比如我这里填的FirstApp

下面简单介绍一下各部分的作用:

  1. Name:项目名,比如QQ、微信这类手机App,它们的项目名称大概率就是QQ、WeChat之类的,注意项目名最好不要用中文。
  2. Package name:包名,由于安卓最开始是与Java强绑定在一起的,这实际上属于Java中的语法范畴,这相当于是将我们的APP代码也看做一个代码库,同时我们也能引入别人写的库,而这就是在设置这个代码库的名称,其规则一般是倒序,反应的是目录结构,比如这里是先是顶层的com,然后是例子example,最后是我们的名称firstapp,它会根据我们填入的项目名自动生成,不用管。
  3. Save Location:保存位置,我这里直接默认了,如果你不想保存在C盘,可以自行更换路径
  4. Minimum SDK:使用的最小SDK版本,安卓应用程序开发本质上就是调用各种安卓开发库,而这里的SDK指的就是安卓官方的开发库,理论上SDK版本越早,那么开发出来的应用程序支持的设备就越多,比如这里的下一行写的就是该SDK可以支持97.4%的设备,当然你也可以修改这里的版本,但一般选择这里默认的即可,由于不同版本SDK支持的功能并不完全相同,所以推荐你选择我这里所使用的SDK版本。
  5. Build configuration language:构建我们app的配置文件所用语言,一般也是直接默认选择这里的Kotlin即可。

最后点击完成。

在进入我们新建的项目之后,它会默认执行构建脚本,如果不存在指定版本的gradle构建包,就会自动取拉取。

image.png

只有完成了这一步,我们的项目才算真的建立完成。

这里的gradle构建系统,和C++中的cmake、rust中的cargo等项目管理工具类似,就是用来帮助我们添加各种第三方包、配置项目属性、编译构建我们代码成为最终app的。

由于安卓开发中默认用到了大量的文件,因此为了方便使用,android提供了不同的文件展示方式,常用的就是下面两个:

image.png

其中“项目”指的就是像文件管理器一样显示目录,选择它后你会发现,整个项目目录非常繁杂,甚至你需要点开四五个文件夹才能找到我们的代码文件,所以实际开发中我们一般不会选择这个。

我们大多数时候选择的都是Android这个选项,它会将我们开发App所需要的资源、代码文件分类整理好,可以让我们快速找到目标文件。

image.png

比如上面图中,我们可以快速看到重要的目录与文件:

  1. manifests:该文件存放清单文件,当安卓系统运行我们程序时,就是通过这个文件知道我们程序所需要哪些权限、限制哪些设备能用等等。
  2. kotlin+java:我们的代码所在,日后我们的代码也将在这个文件中完成,比如其自动生成的入口文件MainActivity.kt就在这个文件夹下。
  3. res:资源文件,比如各种图片、音乐等等,都将放在这个目录下。
  4. Gradle Scripts:grade构建脚本目录,用于配置grade这个构建系统的,比如当我们需要添加某个第三方包、修改代理配置等等,都是在这个目录中找到配置文件进行修改。

3.App代码速览

然后我们开始进入App的代码开发环节,让你可以快速上手开发App,如果遇到不理解的,直接询问deepseek即可。

当新建一个空项目之后,进入入口文件,可以看到其默认为我们实现了一个类与两个方法:

image.png

其中最前面的MainActivity继承自ComponentActivity,它是我们的程序入口,也就是当我们App跑起来之后,第一步就是找到这个类,然后执行它里面的入口函数。

你可能会问为什么是它?我能修改它吗?

这当然是可以的:

image.png

如果你想要修改这个入口类的名字,那么你就需要同步修改配置文件中的信息,之所以这里MainActivity会是入口类,仅仅只是因为配置文件中默认写的是它而已。

但要注意,虽然你可以修改它的名字,但最好不要修改它的继承关系以及类里面的函数代码,除非你真的理解了它的运行逻辑,否则一旦报错你可能就不太好找出愿意。

中间第二个是一个示例组件函数,它的最前面有一个标注:

@Composable

意思是可组合的,使用kotlin开发App时,尤其需要注意这个标注,都有非常重要的含义。

使用kotlin开发App的基础概念就是,任何UI都是一个可被组合的函数,使用这里的Composable进行标注。

最后第三个函数,它又多了一个标注:

@Preview

这里的意思是预览,可以让我们方便的实时预览展示效果。

比如这里,它的内部代码实际上和前面的入口函数所展示的效果是一模一样的,你可以直接点击它的左边运行它:

image.png

它的效果是每当你修改代码后,就会自动重新构建将效果展示在界面上,但可能是bug,在我这里并没有效果,以后有机会再试试吧~

下面来到入口函数:

image.png

这里的onCreate是安卓开发的入口函数,从函数签名的override我们可以知道,它实际上是重写的父类函数。

因此该函数第一步就是调用父类的onCreate函数,保证父类中的数据可以被正常的初始化,在kotlin中super指代父类,这里的参数可以看它的名称,就是一个保存App状态的实例:

super.onCreate(savedInstanceState)

至于第二个函数,看起名称是启动边到边功能,不懂,那就问问deepseek、浏览器搜一搜。

大概含义就是启用全面屏功能,如果不调用这个函数,当启动我们的App时,手机屏幕边缘可能会存在白边,也就是没有完全被我们的App占满。

最后第三个函数,setContent,意思就是设置我们App程序的内容,这是我们的重点。

注意它这里的写法,看起来特别奇怪:setContent{ ... },这怎么看也不像是在调用一个函数。

这实际上是kotlin中的语法简写,其原本的函数调用代码大致如下:

setContent(null,{ ... })

只不过由于第一个参数有默认值null不需要填,第二个参数为一个尾随的lambda表达式,因此有了这里这种写法(说实话,这种写法我也是第一次见,kotlin对函数调用的简化实在是太狠了)。

setContent(){...}
//由于无参数,可以继续简化
setContent{...}

所以简单来说,这里大括号中的内容,实际上是一个无参lambda表达式作为该函数的最后一个参数。

然后在这个函数里面,调用了一个默认主题FirstAppTheme

FirstAppTheme {  
  ... 
}

这同样也是为我们自动生成的,一般也不需要管:

image.png

可以看到,它的最后一个参数同样是一个尾随lambda表达式,因此它内部的这些内容都是填入这个函数的最后一个参数的。

而它内部的内容就是我们最重要的部分了,因为这就是在写我们App的界面了。

首先是Scaffold,它是一个基本的界面,你可以把它看作我们App的屏幕,因为它的参数modifier值为Modifier.fillMaxSize(),也就是填充最大尺寸。

注意modifier参数,这是所有基本UI组件都存在的一个参数,你可以将其看做前端里面的CSS,也就是布局参数,通过调用Modifier对象上的各种样式函数设置其各种样式。

它的内部便是我们要填充的各种组件了,比如这里默认填充的就是这个Greeting函数组件。

Scaffold(modifier = Modifier.fillMaxSize()){ innerPadding ->  
    Greeting(  
        name = "Android",  
        modifier = Modifier.padding(innerPadding)  
    )  
}

这里的innerPadding参数指的是内边距,这是必要的,因为有些手机有类似刘海屏之内的东西,如果不添加这个边距属性,就可能导致你的软件界面被刘海屏给挡住。

4.记事本App实现

有了前面的基础之后,我们就可以来实现一个最简单的记事本程序了,最终的效果如下:

image.png

首先入口函数的代码我们就不需要动了,只是简单的修改一下greeting函数即可:

image.png

首先将该函数的名字改为了Notepad,并且参数也只接受一个样式的参数。

然后在Notepad函数内部,我声明了四个变量,首先是保存记事本内容的变量note:

作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux