【Android】体系框架-第一行代码起程!
1.Android体系框架[*]Android的体系架构接纳了分层架构的思想。下图为谷歌官方提供的经典分层架构图,从下往上依次分为Linux内核、硬件抽象层(HAL)、体系Native库和Android运行时情况、Java框架层以及应用层这5层架构,其中每一层都包含大量的子模块或子体系。
https://i-blog.csdnimg.cn/direct/b07bb39055764920bafc0c22a3b5c9f5.png
Android底层内核空间以Linux Kernel作为基石,上层用户空间由Native体系库、虚拟机运行情况、框架层组成,通过体系调用(Syscall)连通体系的内核空间与用户空间。对于用户空间主要接纳C++和Java代码编写,通过JNI技术打通用户空间的Java层和Native层(C++/C),从而连通整个体系。
应用程序层(Applications)
[*]这一层装配了一个焦点应用程序集合,包罗欣赏器、联系人、电话、日历、相机等应用;
[*]除此之外,用户开发的Android应用也处于这一层,比如微博、微信、QQ等;
[*]总的来说,应用程序层包罗了所有的Android应用程序,其可以分为体系自带的焦点应用程序以及用户自行开发的应用程序。
应用程序框架层(Application Framework)
它提供了大量可供开发人员利用的应用程序接口(Application Programming Interface,API),Android自带的很多焦点应用也是利用这些API完成的。
[*] 应用程序框架层主要提供的组件如下表所示:
[*] 位置管理器 Location Manager 提供地理位置及定位功能服务
[*] 包管理器 Package Manager
管理所有安装在Android体系中的应用程序
[*] 关照管理器 Notification Manager
使应用程序可以在状态栏中表现自界说的提示信息
[*] 资源管理器 Resource Manager
提供应用程序利用的各种非代码资源,如本地字符串、图片、结构文件、颜色文件等
[*] 电话管理器 Telephony Manager
[*] 管理所有的移动设备功能
[*] 窗口管理器 Window Manager
管理所有开启的窗口程序
[*] 内容提供者 Content Provider
使不同应用程序之间可以共享数据
[*] 视图体系 ViewSystem
丰富的、可扩展的视图集合,可用于构建一个应用程序,包摆列表(Lists)、网格(Grids)、文本框(TextBoxes)、按钮(Buttons),甚至是内嵌的Web欣赏器
应用程序框架层会合了很多Android开发必要的组件,其中最主要的就是Activities(活动)、Broadcast Receiver(广播接收器)、Services(服务)以及Content Providers(内容提供者)这四大组件。
运行库层(Libraries and Android Runtime)
体系库
[*]Android包含一些原生C/C++库,这些库能够被安卓体系的不同组件利用。它们通过Android应用框架为开发者提供服务。
[*]开发者可以通过调用Java API Framework来利用原生库的功能,也可以用Android NDK直接调用原生库。
[*]体系库包罗九个子体系,分别是:
体系C语言库标准C语言体系库 (libc) 的 BSD 衍生,调解为基于嵌入式 Linux 设备多媒体库基于 PacketVideo 的 OpenCORE,这些库支持播放和录制许多流行的音频和视频格式,以及静态图像文件,包罗 MPEG4、H.264、MP3、AAC、AMR、JPG、PNG图层管理(Surface Manager)对表现子体系的管理,而且为多个应用程序提供 2D 和 3D 图层的无缝融合SQLite轻量级关系数据库引擎3D库基于OpenFLES1.0 APLs实现,该库可以利用硬件3D加速大概利用高度优化3D软加速FreeType位图与矢量字体表现渲染LibWebCore新式的 Web 欣赏器引擎,支持 Android 欣赏器和内嵌的 Web 视图SGL内置的2D图形引擎SSL支持数据通信 Android运行时
Dalvik虚拟机(在Android 5.0之前):一种专为移动设备优化的Java虚拟机。
ART(Android Runtime)**(在Android 5.0及之后):替换Dalvik虚拟机,提供更好的性能和垃圾回收机制。
[*]Android运行时包罗焦点库以及Dalvik虚拟机(Android 5.0以后更改为ART虚拟机)。
[*]前者既兼容了大多数Java语言所必要的功能函数,又包罗了Android的焦点库,比如android.os、http://android.net、android.media等。
[*]后者是一种基于寄存器的Java虚拟机,每一个Android应用都运行在单独的进程中,拥有一个独立的Dalvik虚拟机实例。
Dalvik虚拟机概述
[*]Google为Android平台专门设计的一套虚拟机来运行Android应用程序,那就是Dalvik虚拟机(Dalvik Virtual Machine,DVM)。 留意:只管Android应用程序是通过Java语言来开发的,但其并不是运行在标准的Java虚拟机上。
DalVik虚拟机作为Android平台的焦点组件,拥有如下特点: 1. 体积小,占用内存空间小; 2. 实行专有的DEX(Dalvik Executable)文件格式,体积更小,实行速率更快; 3. 常量池接纳32位索引值,寻址类方法名、字段名、常量更快; 4. 基于寄存器架构,并拥有一套完备的指令体系; 5. 提供对生命周期的管理、堆栈的管理、线程的管理、安全和异常的管理以及垃圾回收等重要功能; 6. 所有Android应用程序都运行在Android体系进程里,每个进程对于一个Dalvik虚拟机实例。
[*]Dalvik虚拟机接纳的是JIT(Just-in-time Compilation,即时编译)技术,在运行应用时将字节码翻译为呆板码,从而使程序的实行速率更快。但随着硬件程度的不断发展以及人们对更高性能的需求,Dalvik虚拟机的不敷日益突出。
[*]Google在2014年推出了新的虚拟机ART,并从Android5.0开始废弃了Dalvik,全面推行ART。ART虚拟机接纳AOT(Ahead-of-time)技术,在应用程序安装时就会将字节码转换为呆板码,从而优化了应用运行的速率。在内存管理方面,ART也有比较大的改进,对内存分配和回收都做了算法优化,降低了内存碎片化程度,回收时间也得以缩短。
Dalvik虚拟机与Java虚拟机的区别
Dalvik虚拟机Java虚拟机虚拟机架构基于寄存器架构,数据访问通过寄存器间直接通报,编译和运行都会更快一些基于栈架构,编译和运行会慢一些字节码实行.dex格式的Dalvik字节码,由.class文件通过Android SDK目次下名为dx的工具压缩后产生的,体积更小实行.class格式的Java字节码运行情况一个应用启动会运行一个单独的虚拟机,运行在独立的进程中所有应用都运行在同一个虚拟机中 硬件抽象层HAL(Hardware Abstraction Layer)
[*]硬件抽象层处于应用程序框架层和Linux内核驱动之间,用于将硬件抽象化。简单来说,就是对内核驱动程序举行封装,向上提供接口,向下屏蔽详细实现细节。
[*]体系抽象层包含多个库模块,每个模块都为特定范例的硬件组件实现接口,例如相机、蓝牙模块。
[*]当应用程序框架层API要访问设备硬件时,Android体系会为该硬件组件加载库模块。
Linux内核层(Linux Kernel)
[*]Android基于Linux提供焦点体系服务,例如安全、内存管理、进程管理、网络堆栈、驱动模子。
[*]除了标准的 Linux 内核外,Android 还增长了内核的驱动程序,如Binder(IPC)驱动、表现驱动、输入设备驱动、音频体系驱动、摄像头驱动、WiFi驱动、蓝牙驱动、电源管理。
四大组件
1. Activity(活动)
Activity是Android应用程序的门面,主要用于构建应用的用户界面。每个Activity通常对应一个屏幕,用户能在这个屏幕上举行交互操作。Activity管理应用的UI结构,并处理用户的输入和导航。
[*]特点:
[*]用户界面:展示应用的UI。
[*]生命周期:Activity有一套完备的生命周期管理方法,如onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()等,用于管理其状态厘革。
[*]交互逻辑:处理用户输入和事件。
2. Service(服务)
Service是一个可以在后台长时间运行的组件。它不提供用户界面,但可以实行必要持续举行的操作,如播放音乐、下载文件或实行网络哀求。
[*]特点:
[*]后台运行:可以在后台运行,即利用户退出应用。
[*]无UI:不提供用户界面。
[*]生命周期:Service也有本身的生命周期管理方法,如onCreate()、onStartCommand()、onBind()、onDestroy()等。
3. BroadcastReceiver(广播接收器)
BroadcastReceiver允许应用接收并处理广播消息。广播可以来自体系或其他应用,用于关照一些全局的事件,如电量厘革、网络状态厘革、短信接收等。
[*]特点:
[*]接收广播:能够接收和处理广播消息。
[*]无持续运行:广播接收器在处理完广播后会立即停止,不会长期运行。
[*]动态和静态注册:可以在代码中动态注册,也可以在AndroidManifest.xml文件中静态注册。
4. ContentProvider(内容提供者)
ContentProvider为应用程序之间共享数据提供了同一的接口。它可以用来存储和检索数据,并允许不同应用访问这些数据。常见的利用场景包罗访问联系人、图片、视频等。
[*]特点:
[*]数据共享:允许应用程序之间共享数据。
[*]标准接口:提供一套标准的接口用于数据的CRUD操作(创建、读取、更新、删除)。
[*]URI标识:通过URI标识要访问的数据。
示例利用场景
[*]Activity:
[*]打开一个新的界面,例如启动一个新的Activity来表现详细信息。
[*]Service:
[*]播放配景音乐,即利用户切换到其他应用,音乐仍然在后台播放。
[*]BroadcastReceiver:
[*]当收到新短信时表现关照,大概当网络状态厘革时关照用户。
[*]ContentProvider:
[*]读取体系通讯录中的联系人信息并表现在应用中。
分析android程序
1.project项目结构
https://i-blog.csdnimg.cn/direct/19212460188844d9826efd822c0c4b04.png
[*].gradle和.idea
[*]这两个目次下放置的都是Android Studio自动天生的一些文件,我们无须关心,也不要去手动编辑
[*]app
[*]项目中的代码、资源等内容都是放置在这个目次下的,我们反面的开发工作也基本是在这个目次下举行的,待会儿还会对这个目次单独展开解说。
[*]build
[*]这个目次主要包含了一些在编译时自动天生的文件,你也不必要过多关心
[*]gradle
[*]这个目次下包含了gradle wrapper的配置文件,利用gradle wrapper的方式不必要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否必要联网下载gradle。
[*]Android Studio默认就是启用gradle wrapper方式的,如果必要更改成离线模式,可以点击Android Studio导航栏→File→Settings→Build, Execution,Deployment→Gradle,举行配置更改
[*].gitignore
[*]这个文件是用来将指定的目次或文件排除在版本控制之外的。
[*]build.gradle
[*]这是项目全局的gradle构建脚本,通常这个文件中的内容是不必要修改的。稍后我们将会详细分析gradle构建脚本中的详细内容。
[*]gradle.properties
[*]这个文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本。
[*]gradlew和gradlew.bat
[*]这两个文件是用来在下令行界面中实行gradle下令的,
[*]其中gradlew是在Linux或Mac体系中利用的,gradlew.bat是在Windows体系中利用的。
[*]HelloWorld.imliml
[*]文件是所有IntelliJ IDEA项目都会自动天生的一个文件(Android Studio是基于IntelliJIDEA开发的),用于标识这是一个IntelliJ IDEA项目,我们不必要修改这个文件中的任何内容。
[*]local.properties
[*]这个文件用于指定本机中的Android SDK路径,通常内容是自动天生的,我们并不必要修改。除非你本机中的Android SDK位置发生了厘革,那么就将这个文件中的路径改成新的位置即可。
[*]settings.gradle
[*]这个文件用于指定项目中所有引入的模块。由于HelloWorld项目中只有一个app模块,因此该文件中也就只引入了app这一个模块。通常情况下,模块的引入是自动完成的,必要我们手动修改这个文件的场景可能比较少
2.app目次下的结构
https://i-blog.csdnimg.cn/direct/7d44fc77315a4725b497e8c246d6a117.png
[*]build
[*]这个目次和外层的build目次雷同,也包含了一些在编译时自动天生的文件,不过它内里的内容会更加复杂,我们不必要过多关心。
[*]libs
[*]如果你的项目中利用到了第三方jar包,就必要把这些jar包都放在libs目次下,放在这个目次下的jar包会被自动添加到项目标构建路径里。
[*]androidTest
[*]此处是用来编写Android Test测试用例的,可以对项目举行一些自动化测试。
[*]java
[*]毫无疑问,java目次是放置我们所有Java代码的地方(Kotlin代码也放在这里),展开该目次,你将看到体系帮我们自动天生了一个MainActivity文件。
[*]res
[*]这个目次下的内容就有点多了。简单点说,就是你在项目中利用到的所有图片、结构、字符串等资源都要存放在这个目次下。
[*]当然这个目次下另有很多子目次,图片放在drawable目次下,结构放在layout目次下,字符串放在values目次下,所以你不用担心会把整个res目次弄得乱糟糟的。
[*]AndroidManifest.xml
[*]这是整个Android项目标配置文件,你在程序中界说的所有四大组件都必要在这个文件里注册,别的还可以在这个文件中给应用程序添加权限声明。由于这个文件以后会经常用到,我们等用到的时间再做详细阐明。
[*]test
[*]此处是用来编写Unit Test测试用例的,是对项目举行自动化测试的另一种方式。
[*].gitignore
[*]这个文件用于将app模块内指定的目次或文件排除在版本控制之外,作用和外层的.gitignore文件雷同。
[*]app.iml
[*]IntelliJ IDEA项目自动天生的文件,我们不必要关心或修改这个文件中的内容。
[*]build.gradle
[*]这是app模块的gradle构建脚本,这个文件中会指定很多项目构建相干的配置,我们稍后将会详细分析gradle构建脚本中的详细内容。
[*]proguard-rules.pro
[*]这个文件用于指定项目代码的混淆规则,今世码开发完成后打包成安装包文件,如果不希望代码被别人破解,通常会将代码举行混淆,从而让破解者难以阅读。
3.“Hello World! ”在哪里
Android-Manifest.xml文件
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
这段代码表现对MainActivity举行注册,没有在AndroidManifest.xml里注册的Activity是不能利用的。
其中intent-filter里的两行代码非常重要, 和表现MainActivity是这个项目标主Activity,在手机上点击应用图标,首先启动的就是这个Activity。
Activity是Android应用程序的门面,凡是在应用中你看得到的东西,都是放在Activity中的
MainActivity文件
书中
https://i-blog.csdnimg.cn/direct/a82c619842ab47faac1d02749a3d8fa9.png
首先可以看到,MainActivity是继承自AppCompatActivity的。
AppCompatActivity是AndroidX中提供的一种向下兼容的Activity,可以使Activity在不同体系版本中的功能保持划一性。
而Activity类是Android体系提供的一个基类,我们项目中所有自界说的Activity都必须继承它大概它的子类才能拥有Activity的特性(AppCompatActivity是Activity的子类)。
然后可以看到MainActivity中有一个onCreate()方法,这个方法是一个Activity被创建时必定要实行的方法,其中只有两行代码,而且没有“Hello World! ”的字样。
新版
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}
super.onCreate(savedInstanceState);
[*]作用:调用父类 Activity 的 onCreate 方法,实行基类的初始化代码。这是确保Activity生命周期方法正常工作的须要步骤。
EdgeToEdge.enable(this);
[*]作用:启用Edge-to-Edge模式,使Activity可以利用整个屏幕区域,包罗体系栏。详细实现可能依赖于自界说的 EdgeToEdge 类。
setContentView(R.layout.activity_main);
[*]作用:设置Activity的结构资源。R.layout.activity_main 指向一个XML结构文件,界说了这个Activity的用户界面。
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { ... });
[*]作用:设置一个窗口内边距监听器,监听体系窗口内边距的厘革(如状态栏和导航栏)。
[*]详细步骤:
[*]findViewById(R.id.main):找到结构中的 main 视图。
[*]ViewCompat.setOnApplyWindowInsetsListener:设置一个监听器,在窗口内边距发生厘革时调用。
[*](v, insets) -> { ... }:Lambda表达式,界说了在窗口内边距发生厘革时实行的代码。
[*]Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());:获取体系栏的内边距(状态栏和导航栏)。
[*]v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);:根据体系栏的内边距设置视图的添补。
[*]return insets;:返回原始的内边距对象。
整体流程
[*]调用父类的 onCreate 方法:确保Activity生命周期的正常运作。
[*]启用Edge-to-Edge模式:使内容可以延伸到体系栏区域。
[*]设置内容视图:加载并表现结构文件 activity_main。
[*]设置窗口内边距****监听器:调解视图的添补,使其内容不会被体系栏遮挡。
那么“Hello World! ”是在哪里界说的呢?着实Android程序的设计讲求逻辑和视图分离,因此是不保举在Activity中直接编写界面的。
一种更加通用的做法是,在结构文件中编写界面,然后在Activity中引入进来。
可以看到,在onCreate()方法的第二行调用了setContentView()方法,就是这个方法给当前的Activity引入了一个activity_main结构,那“Hello World!”一定就是在这里界说的了!我们快打开这个文件看一看
结构文件都是界说在res/layout目次下的,当你展开layout目次,你会看到activity_main.xml这个文件。打开该文件并切换到Text视图,代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
上面代码中有一个TextView,这是Android体系提供的一个控件,用于在结构中表现文字。
然后你终于在TextView中看到了“Hello World!”的字样!哈哈!终于找到了,原来就是
通过android:text="Hello World!"这句代码界说的
4.res目次下的结构
https://i-blog.csdnimg.cn/direct/de36e1ab5e084d3da9982b15c8ef8e90.png
看到这么多的子目次也不用畏惧,着实归纳一下,res目次中的内容就变得非常简单了。
所有以“drawable”开头的目次都是用来放图片的,
所有以“mipmap”开头的目次都是用来放应用图标的,
所有以“values”开头的目次都是用来放字符串、样式、颜色等配置的,
所有以“layout”开头的目次都是用来放结构文件的。
怎么样,是不是忽然感觉清楚了很多?
之所以有这么多“mipmap”开头的目次,着实主要是为了让程序能够更好地兼容各种设备。
drawable目次也是相同的原理,虽然Android Studio没有帮我们自动天生,但是我们应该本身创建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等目次。在制作程序的时间,最好能够给同一张图片提供几个不同分辨率的版本,分别放在这些目次下,然后程序运行的时间,会自动根据当前运行设备分辨率的高低选择加载哪个目次下的图片。当然这只是理想情况,更多的时间美工只会提供给我们一份图片,这时你把所有图片都放在drawable-xxhdpi目次下就好了,因为这是最主流的设备分辨率目次。
知道了res目次下每个子目次的含义,我们再来看一下如何利用这些资源吧。
打开res/values/strings.xml文件,内容如下所示
<resources>
<string name="app_name">Hellow World</string>
</resources>
可以看到,这里界说了一个应用程序名的字符串,我们有以下两种方式来引用它。
[*]在代码中通过R.string.app_name可以获得该字符串的引用。
[*]在XML中通过@string/app_name可以获得该字符串的引用。
基本的语法就是上面这两种方式,
其中string部分是可以更换的,
如果是引用的图片资源就可以更换成drawable,
如果是引用的应用图标就可以更换成mipmap,
如果是引用的结构文件就可以更换成layout
打开AndroidManifest.xml文件,找到如下代码:
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HellowWorld"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
其中,HelloWorld项目标应用图标就是通过android:icon属性指定的,应用的名称则是通过android:label属性指定的。可以看到,这里对资源引用的方式正是我们刚刚学过的在XML中引用资源的语法。
build.gradle文件
不同于Eclipse,Android Studio是接纳Gradle来构建项目标。Gradle是一个非常先辈的项目构建工具,它利用了一种基于Groovy的领域特定语言(DSL)来举行项目设置,摒弃了传统基于XML(如Ant和Maven)的各种烦琐配置。
HelloWorld项目中有两个build.gradle文件,一个是在最外层目次下的,一个是在app目次下的。
这两个文件对构建Android Studio项目都起到了至关重要的作用,下面我们就来对这两个文件中的内容举行详细的分析。先来看一下最外层目次下的build.gradle文件,代码如下所示:
https://i-blog.csdnimg.cn/direct/ea721eabcd6845188a39df64bc89e654.png
上为书中原代码,下为当前as版本的代码
plugins {
alias(libs.plugins.android.application)
}
android {
namespace 'com.example.hellowworld'
compileSdk 34
defaultConfig {
applicationId "com.example.hellowworld"
minSdk 31
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation libs.appcompat
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
}
1.Gradle插件是配置项目构建和管理依赖项
书中
https://i-blog.csdnimg.cn/direct/193a06605fb14ff49f98534322aad511.png
这个文件中的内容就要相对复杂一些了,下面我们一行行地举行分析。首先第一行应用了一个插件,一般有两种值可选:com.android.application表现这是一个应用程序模块,
com.android.library表现这是一个库模块。二者最大的区别在于,应用程序模块是可以直接运行的,库模块只能作为代码库依附于别的应用程序模块来运行。
接下来的两行应用了kotlin-android和kotlin-android-extensions这两个插件。如果你想要利用Kotlin来开发Android项目,那么第一个插件就是必须应用的。而第二个插件帮助我们实现了一些非常好用的Kotlin扩展功能,在反面的章节中,你将能体会到它所带来的巨大便利性。
新版
plugins {
alias(libs.plugins.android.application)
}
第一利用用版本目次 (alias) 的 plugins 块,
要在项目标gradle目次下创建一个 libs.versions.toml 文件,用于界说插件和库的版本。
在项目根级的 build.gradle.kts 文件中启用版本目次,并加载 libs.versions.toml 文件。
在 settings.gradle.kts 文件中配置插件管理。
在应用模块的 build.gradle.kts 文件中,利用 alias 来应用插件,并引用版本目次中的插件和依赖项。
这里是关于这个插件的利用(在看书时,发现第一行代码的2,3版不一样,而且与当前的as的配置文件也不一样)
Gradle插件利用
2.android闭包
1.defaultConfig
书中
紧接着是一个大的android闭包,在这个闭包中我们可以配置项目构建的各种属性。
其中,compileSdkVersion用于指定项目标编译版本,这里指定成29表现利用Android 10.0体系的SDK编译。
buildToolsVersion用于指定项目构建工具的版本,目前最新的版本就是29.0.2,如果有更新的版本时,Android Studio会举行提示。
标红部分被高亮标红部分替换
新版
namespace
[*]作用:指定应用程序的定名空间。这是Java/Kotlin包名的替换方案,在应用模块的源码包名和资源包名之间建立联系。它用于唯一标识应用程序,特别是在混淆和打包时利用。
compileSdk
[*]作用:指定编译应用程序时利用的Android SDK版本。这个版本决定了应用程序可以利用的API和功能。通常,建议利用最新的稳定版本。
[*]版本 34:表现编译时利用的Android 34版SDK。
defaultConfig
defaultConfig 块界说了应用程序的默认配置。下面是各个配置项的详细阐明:
applicationId
[*]作用:唯一标识应用程序。这个ID在整个应用程序的生命周期内保持稳定,通常遵照域名反转的定名规则。
[*]示例值:com.example.hellowworld
minSdk
[*]作用:指定应用程序支持的最低Android SDK版本。应用程序将无法在低于该版本的设备上安装和运行。
[*]版本 31:表现应用程序至少支持Android 12(API 31)。
targetSdk
[*]作用:指定应用程序的目标Android SDK版本。这个版本表现应用程序经过测试并优化的SDK版本。目标版本可以启用新版本的举动和功能,同时保持旧版本的兼容性。
[*]版本 34:表现应用程序针对Android 34举行优化。
versionCode
[*]作用:应用程序的内部版本号,每次发布新版本时都应递增。它用于区分不同的版本,特别是在应用商店中举行版本管理时。
[*]示例值:1(初始版本)
versionName
[*]作用:应用程序的版本名称,对用户可见。它可以包含任何字符串,通常用来表现人类可读的版本号。
[*]示例值:1.0(初始版本)
testInstrumentationRunner
[*]作用:指定用于运行Android仪器化测试的运行器类。通常利用AndroidX提供的 AndroidJUnitRunner 来运行JUnit测试。
[*]示例值:androidx.test.runner.AndroidJUnitRunner
2.buildTypes
buildTypes闭包中用于指定天生安装文件的相干配置,通常只会有两个子闭包:一个是debug,一个是release。debug闭包用于指定天生测试版安装文件的配置,release闭包用于指定天生正式版安装文件的配置。
别的,debug闭包是可以忽略不写的,因此我们看到上面的代码中就只有一个release闭包。
下面来看一下release闭包中的详细内容吧,
[*]minifyEnabled用于指定是否对项目标代码举行混淆,true表现混淆,false表现不混淆。
[*]proguardFiles用于指定混淆时利用的规则文件,这里指定了两个文件:
[*]第一个proguard-android-optimize.txt是在/tools/proguard目次下的,内里是所有项目通用的混淆规则;
[*]第二个proguard-rules.pro是在当前项目标根目次下的,内里可以编写当前项目特有的混淆规则。
必要留意的是,通过Android Studio直接运行项目天生的都是测试版安装文件,关于如何天生正式版安装文件,我们将会在之后学习。
此处新版与书中一样,不再赘述。
3.compileOptions(新版有的,书中没有该代码)
属性
[*]sourceCompatibility:指定Java源代码的版本。这个版本界说了代码中的语法和语言特性。
[*]targetCompatibility:指定编译后的字节码的版本。这个版本界说了天生的字节码可以在哪些版本的Java虚拟机上运行。
示例
kotlin
复制代码
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
上面的配置指定了Java 8作为源代码和目标字节码的版本。这意味着你可以在代码中利用Java 8的语言特性,而且天生的字节码可以在支持Java 8的JVM上运行。
3.dependencies
这个闭包的功能非常强大,它可以指定当前项目所有的依赖关系。
通常Android Studio项目一共有3种依赖方式:本地依赖、库依赖和远程依赖。
本地依赖可以对本地的jar包或目次添加依赖关系,
库依赖可以对项目中的库模块添加依赖关系,
远程依赖则可以对jcenter堆栈上的开源项目添加依赖关系。
书中:
https://i-blog.csdnimg.cn/direct/e4f4c49dc64e478fa237f0c623718cc7.png
[*]implementation fileTree就是一个本地依赖声明,它表现将libs目次下所有.jar后缀的文件都添加到项目标构建路径中。
[*]implementation则是远程依赖声明,
[*]androidx.appcompat:appcompat:1.1.0就是一个标准的远程依赖库格式,
[*]其中androidx.appcompat是域名部分,用于和其他公司的库做区分;
[*]appcompat是工程名部分,用于和同一个公司中不同的库工程做区分;
[*]1.1.0是版本号,用于和同一个库不同的版本做区分。加上这句声明后,Gradle在构建项目时会首先检查一下本地是否已经有这个库的缓存,如果没有的话则会自动联网下载,然后再添加到项目标构建路径中。
[*]至于库依赖声明这里没有用到,它的基本格式是implementation project反面加上要依赖的库的名称,
[*]比如有一个库模块的名字叫helper,那么添加这个库的依赖关系只必要到场implementation project(‘:helper’)这句声明即可。
别的剩下的testImplementation和androidTestImplementation都是用于声明测试用例库的,这个我们暂时用不到,先忽略它就可以了
新版
dependencies {
implementation libs.appcompat
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
testImplementation libs.junit
androidTestImplementation libs.ext.junit
androidTestImplementation libs.espresso.core
}
依赖项表明
implementation
[*]作用:implementation 配置表现该依赖项在编译和运行时都必要。
[*]例子:
[*]implementation libs.appcompat:引用 androidx.appcompat 库,提供兼容性支持,用于向后兼容的应用程序开发。
[*]implementation libs.material:引用 com.google.android.material 库,用于利用Material Design组件。
[*]implementation libs.activity:引用 androidx.activity 库,提供Activity相干的扩展功能。
[*]implementation libs.constraintlayout:引用 androidx.constraintlayout 库,用于创建复杂结构的ConstraintLayout组件。
testImplementation
[*]作用:testImplementation 配置表现该依赖项仅在运行单位测试时必要。
[*]例子:
[*]testImplementation libs.junit:引用 junit 库,用于编写和运行单位测试。
androidTestImplementation
[*]作用:androidTestImplementation 配置表现该依赖项仅在运行Android仪器化测试时必要。
[*]例子:
[*]androidTestImplementation libs.ext.junit:引用 androidx.test.ext 库,用于在Android情况中运行JUnit测试。
[*]androidTestImplementation libs.espresso.core:引用 androidx.test.espresso 库,用于编写UI测试。
日记工具
利用Android的日记工具
LogAndroid中的日记工具类是Log(android.util.Log),
这个类中提供了如下5个方法来供我们打印日记。
[*]Log.v()。
[*]用于打印那些最为琐碎的、意义最小的日记信息。对应级别verbose,是Android日记内里级别最低的一种。
[*]Log.d()。
[*]用于打印一些调试信息,这些信息对你调试程序和分析问题应该是有帮助的。对应级别debug,比verbose高一级。
[*]Log.i()。
[*]用于打印一些比较重要的数据,这些数据应该是你非常想看到的、可以帮你分析用户举动的数据。对应级别info,比debug高一级。
[*]Log.w()。
[*]用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好去修复一下这些出现警告的地方。对应级别warn,比info高一级。
[*]Log.e()。
[*]用于打印程序中的错误信息,比如程序进入了catch语句中。当有错误信息打印出来的时间,一般代表你的程序出现严重问题了,必须尽快修复。对应级别error,比warn高一级。
着实很简单,一共就5个方法,当然每个方法还会有不同的重载,但那对你来说肯定不是什么难理解的地方了。我们现在就在HelloWorld项目中试一试日记工具好不好用吧。
打开MainActivity,在onCreate()方法中添加一行打印日记的语句,如下所示:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
Log.d("MainActivity", "onCreate execute");
}
Log.d()方法中传入了两个参数:
[*]第一个参数是tag,一般传入当前的类名就好,主要用于对打印信息举行过滤;
[*]第二个参数是msg,即想要打印的详细内容。
现在可以重新运行一下HelloWorld这个项目了,点击顶部工具栏上的运行按钮,大概利用快捷键Shift + F10(Mac体系是control + R)。
等程序运行完毕,点击Android Studio底部工具栏的“Android Monitor”,在Logcat中就可以看到打印信息了
https://i-blog.csdnimg.cn/direct/723ec84a9a5f42ccb7c7642301598a2d.png
Logcat中的打印信息
其中,你不仅可以看到打印日记的内容和tag名,就连程序的包名、打印的时间以及应用程序的进程号都可以看到。
当然,Logcat中不光会表现我们所打印的日记,还会表现许多其他程序打印的日记,因此在很多情况下还必要对日记举行过滤
为什么利用Log而不利用println()
为什么System.out.println()和println()方法会这么不受待见呢?经过我仔细分析之后,发现这两个方法除了利用方便一点之外,其他就一无是处了。方便在哪儿呢?在AndroidStudio中你只必要输入“sout”,然后按下代码提示键,方法就会自动出来了,信赖这也是很多Java新手对它钟情的缘故原由。
那缺点又在哪儿了呢?这个就太多了,比如日记开关不可控制、不能添加日记标签、日记没有级别区分…听我说了这些,你可能已经不太想用System.out.println()和println()方法了,
那么Log就把上面所说的缺点全部改好了吗?虽然谈不上全部,但我以为Log已经做得相当不错了。我现在就来带你看看Log和Logcat配合的强大之处
过滤器
首先,Logcat中可以很轻松地添加过滤器
目前只有3个过滤器,Show only selected application表现只表现当前选中程序的日记;
Firebase是Google提供的一个开发者工具和基础架构平台,我们可以不用管它;
No Filters相当于没有过滤器,会把所有的日记都表现出来。
那可不可以自界说过滤器呢?当然可以,我们现在就来添加一个过滤器试试。
[*]点击“Edit Filter Configuration”,会弹出一个过滤器配置界面。
[*]我们给过滤器起名叫data,而且让它对名为data的tag举行过滤。
[*]点击“OK”,你会发现多出了一个data过滤器。
[*]当选中这个过滤器的时间,刚才在onCreate()方法里打印的日记就不见了,这是因为data这个过滤器只会表现tag名称为data的日记。
[*]你可以尝试在onCreate()方法中把打印日记的语句改成Log.d(“data”, “onCreateexecute”),然后再次运行程序,你就会在data过滤器下看到这行日记了
以上是老版本过滤器,不实用于2022十月之后的。
下来是新版利用方法:
https://i-blog.csdnimg.cn/direct/9886304e9a234bab81062b49da48e675.png
在绿色的packege反面用空格加上tag:date就可以达到上述结果,除此之外另有其他的更多的过滤方法,有大佬举行了整理。
level: 表现log的等级,对应debug、error等等
package: 代表包名
tag: 代表标签筛选
-tag: 则代表过滤标签,设置的tag不表现
这里我们直接上链接
https://blog.csdn.net/qq_20451879/article/details/134694630
https://blog.csdn.net/woailinqingxia/article/details/134820595
也可以过滤其中的几项。按本身需求过滤
老版本的只能过滤一个包名,或一个TAG,或关键字,新版本的还是很好用的。
日记
看完了过滤器,再来看一下Logcat中的日记级别控制吧。Logcat中主要有5个级别,分别对应上一小节先容的5个方法
当前我们选中的级别是Verbose,也就是最低等级。这意味着不管我们利用哪一个方法打印日记,这条日记都一定会表现出来。而如果我们将级别选中为Debug,这时只有我们利用Debug
及以上级别方法打印的日记才会表现出来,以此类推。你可以做一下实验,当你把Logcat中的级别选中为Info、Warn大概Error时,我们在onCreate()方法中打印的语句是不会表现的,因为我们打印日记时利用的是Log.d()方法
器下看到这行日记了
以上是老版本过滤器,不实用于2022十月之后的。
下来是新版利用方法:
[外链图片转存中…(img-80VzIoQ4-1721461921332)]
在绿色的packege反面用空格加上tag:date就可以达到上述结果,除此之外另有其他的更多的过滤方法,有大佬举行了整理。
level: 表现log的等级,对应debug、error等等
package: 代表包名
tag: 代表标签筛选
-tag: 则代表过滤标签,设置的tag不表现
这里我们直接上链接
https://blog.csdn.net/qq_20451879/article/details/134694630
https://blog.csdn.net/woailinqingxia/article/details/134820595
也可以过滤其中的几项。按本身需求过滤
老版本的只能过滤一个包名,或一个TAG,或关键字,新版本的还是很好用的。
日记
看完了过滤器,再来看一下Logcat中的日记级别控制吧。Logcat中主要有5个级别,分别对应上一小节先容的5个方法
当前我们选中的级别是Verbose,也就是最低等级。这意味着不管我们利用哪一个方法打印日记,这条日记都一定会表现出来。而如果我们将级别选中为Debug,这时只有我们利用Debug
及以上级别方法打印的日记才会表现出来,以此类推。你可以做一下实验,当你把Logcat中的级别选中为Info、Warn大概Error时,我们在onCreate()方法中打印的语句是不会表现的,因为我们打印日记时利用的是Log.d()方法
看完了吧,看完了别看了,上面看的没用,直接看上面链接就行
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]