【Android】体系框架-第一行代码起程!

打印 上一主题 下一主题

主题 828|帖子 828|积分 2484

1.Android体系框架



  • Android的体系架构接纳了分层架构的思想。下图为谷歌官方提供的经典分层架构图,从下往上依次分为Linux内核、硬件抽象层(HAL)、体系Native库和Android运行时情况、Java框架层以及应用层这5层架构,其中每一层都包含大量的子模块或子体系。

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项目结构



  • .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目次下的结构



  • 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文件

  1. <activity
  2.     android:name=".MainActivity"
  3.     android:exported="true">
  4.     <intent-filter>
  5.         <action android:name="android.intent.action.MAIN" />
  6.         <category android:name="android.intent.category.LAUNCHER" />
  7.     </intent-filter>
  8. </activity>
复制代码
这段代码表现对MainActivity举行注册,没有在AndroidManifest.xml里注册的Activity是不能利用的。
其中intent-filter里的两行代码非常重要, 和表现MainActivity是这个项目标主Activity,在手机上点击应用图标,首先启动的就是这个Activity。
Activity是Android应用程序的门面,凡是在应用中你看得到的东西,都是放在Activity中的
MainActivity文件

书中


首先可以看到,MainActivity是继承自AppCompatActivity的。
   AppCompatActivity是AndroidX中提供的一种向下兼容的Activity,可以使Activity在不同体系版本中的功能保持划一性。
  而Activity类是Android体系提供的一个基类,我们项目中所有自界说的Activity都必须继承它大概它的子类才能拥有Activity的特性(AppCompatActivity是Activity的子类)。
  然后可以看到MainActivity中有一个onCreate()方法,这个方法是一个Activity被创建时必定要实行的方法,其中只有两行代码,而且没有“Hello World! ”的字样。
新版

  1. public class MainActivity extends AppCompatActivity {
  2.     @Override
  3.     protected void onCreate(Bundle savedInstanceState) {
  4.         super.onCreate(savedInstanceState);
  5.         EdgeToEdge.enable(this);
  6.         setContentView(R.layout.activity_main);
  7.         ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
  8.             Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
  9.             v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
  10.             return insets;
  11.         });
  12.     }
  13. }
复制代码
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视图,代码如下所示:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:tools="http://schemas.android.com/tools"
  5.     android:id="@+id/main"
  6.     android:layout_width="match_parent"
  7.     android:layout_height="match_parent"
  8.     tools:context=".MainActivity">
  9.     <TextView
  10.         android:layout_width="wrap_content"
  11.         android:layout_height="wrap_content"
  12.         android:text="Hello World!"
  13.         app:layout_constraintBottom_toBottomOf="parent"
  14.         app:layout_constraintEnd_toEndOf="parent"
  15.         app:layout_constraintStart_toStartOf="parent"
  16.         app:layout_constraintTop_toTopOf="parent" />
  17. </androidx.constraintlayout.widget.ConstraintLayout>
复制代码
上面代码中有一个TextView,这是Android体系提供的一个控件,用于在结构中表现文字。
然后你终于在TextView中看到了“Hello World!”的字样!哈哈!终于找到了,原来就是
通过android:text="Hello World!"这句代码界说的
4.res目次下的结构


看到这么多的子目次也不用畏惧,着实归纳一下,res目次中的内容就变得非常简单了。
   所有以“drawable”开头的目次都是用来放图片的,
  所有以“mipmap”开头的目次都是用来放应用图标的,
  所有以“values”开头的目次都是用来放字符串、样式、颜色等配置的,
  所有以“layout”开头的目次都是用来放结构文件的。
  怎么样,是不是忽然感觉清楚了很多?
之所以有这么多“mipmap”开头的目次,着实主要是为了让程序能够更好地兼容各种设备。
drawable目次也是相同的原理,虽然Android Studio没有帮我们自动天生,但是我们应该本身创建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等目次。在制作程序的时间,最好能够给同一张图片提供几个不同分辨率的版本,分别放在这些目次下,然后程序运行的时间,会自动根据当前运行设备分辨率的高低选择加载哪个目次下的图片。当然这只是理想情况,更多的时间美工只会提供给我们一份图片,这时你把所有图片都放在drawable-xxhdpi目次下就好了,因为这是最主流的设备分辨率目次。
知道了res目次下每个子目次的含义,我们再来看一下如何利用这些资源吧。
打开res/values/strings.xml文件,内容如下所示
  1. <resources>
  2.     <string name="app_name">Hellow World</string>
  3. </resources>
复制代码
可以看到,这里界说了一个应用程序名的字符串,我们有以下两种方式来引用它。

  • 代码中通过R.string.app_name可以获得该字符串的引用。
  • XML中通过@string/app_name可以获得该字符串的引用。
   基本的语法就是上面这两种方式,
  其中string部分是可以更换的,
  如果是引用的图片资源就可以更换成drawable,
  如果是引用的应用图标就可以更换成mipmap,
  如果是引用的结构文件就可以更换成layout
  打开AndroidManifest.xml文件,找到如下代码:
  1. <application
  2.     android:allowBackup="true"
  3.     android:dataExtractionRules="@xml/data_extraction_rules"
  4.     android:fullBackupContent="@xml/backup_rules"
  5.     android:icon="@mipmap/ic_launcher"
  6.     android:label="@string/app_name"
  7.     android:roundIcon="@mipmap/ic_launcher_round"
  8.     android:supportsRtl="true"
  9.     android:theme="@style/Theme.HellowWorld"
  10.     tools:targetApi="31">
  11.     <activity
  12.         android:name=".MainActivity"
  13.         android:exported="true">
  14.         <intent-filter>
  15.             <action android:name="android.intent.action.MAIN" />
  16.             <category android:name="android.intent.category.LAUNCHER" />
  17.         </intent-filter>
  18.     </activity>
  19. </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文件,代码如下所示:

上为书中原代码,下为当前as版本的代码
  1. plugins {
  2.     alias(libs.plugins.android.application)
  3. }
  4. android {
  5.     namespace 'com.example.hellowworld'
  6.     compileSdk 34
  7.     defaultConfig {
  8.         applicationId "com.example.hellowworld"
  9.         minSdk 31
  10.         targetSdk 34
  11.         versionCode 1
  12.         versionName "1.0"
  13.         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  14.     }
  15.     buildTypes {
  16.         release {
  17.             minifyEnabled false
  18.             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  19.         }
  20.     }
  21.     compileOptions {
  22.         sourceCompatibility JavaVersion.VERSION_1_8
  23.         targetCompatibility JavaVersion.VERSION_1_8
  24.     }
  25. }
  26. dependencies {
  27.     implementation libs.appcompat
  28.     implementation libs.material
  29.     implementation libs.activity
  30.     implementation libs.constraintlayout
  31.     testImplementation libs.junit
  32.     androidTestImplementation libs.ext.junit
  33.     androidTestImplementation libs.espresso.core
  34. }
复制代码
1.Gradle插件是配置项目构建和管理依赖项

书中


这个文件中的内容就要相对复杂一些了,下面我们一行行地举行分析。首先第一行应用了一个插件,一般有两种值可选:com.android.application表现这是一个应用程序模块,
com.android.library表现这是一个库模块。二者最大的区别在于,应用程序模块是可以直接运行的,库模块只能作为代码库依附于别的应用程序模块来运行。
   接下来的两行应用了kotlin-android和kotlin-android-extensions这两个插件。如果你想要利用Kotlin来开发Android项目,那么第一个插件就是必须应用的。而第二个插件帮助我们实现了一些非常好用的Kotlin扩展功能,在反面的章节中,你将能体会到它所带来的巨大便利性。
  新版

  1. plugins {
  2.     alias(libs.plugins.android.application)
  3. }
复制代码
第一利用用版本目次 (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虚拟机上运行。
示例
  1. kotlin
  2. 复制代码
  3. android {
  4.     compileOptions {
  5.         sourceCompatibility = JavaVersion.VERSION_1_8
  6.         targetCompatibility = JavaVersion.VERSION_1_8
  7.     }
  8. }
复制代码
上面的配置指定了Java 8作为源代码和目标字节码的版本。这意味着你可以在代码中利用Java 8的语言特性,而且天生的字节码可以在支持Java 8的JVM上运行。
3.dependencies

这个闭包的功能非常强大,它可以指定当前项目所有的依赖关系。
通常Android Studio项目一共有3种依赖方式:本地依赖、库依赖和远程依赖。
   本地依赖可以对本地的jar包或目次添加依赖关系,
  库依赖可以对项目中的库模块添加依赖关系,
  远程依赖则可以对jcenter堆栈上的开源项目添加依赖关系。
  书中:



  • 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都是用于声明测试用例库的,这个我们暂时用不到,先忽略它就可以了
新版

  1. dependencies {
  2.     implementation libs.appcompat
  3.     implementation libs.material
  4.     implementation libs.activity
  5.     implementation libs.constraintlayout
  6.     testImplementation libs.junit
  7.     androidTestImplementation libs.ext.junit
  8.     androidTestImplementation libs.espresso.core
  9. }
复制代码
依赖项表明

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()方法中添加一行打印日记的语句,如下所示:
  1. protected void onCreate(Bundle savedInstanceState) {
  2.     super.onCreate(savedInstanceState);
  3.     EdgeToEdge.enable(this);
  4.     setContentView(R.layout.activity_main);
  5.     ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
  6.         Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
  7.         v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
  8.         return insets;
  9.     });
  10.     Log.d("MainActivity", "onCreate execute");
  11. }
复制代码
Log.d()方法中传入了两个参数:

  • 第一个参数是tag,一般传入当前的类名就好,主要用于对打印信息举行过滤;
  • 第二个参数是msg,即想要打印的详细内容。
现在可以重新运行一下HelloWorld这个项目了,点击顶部工具栏上的运行按钮,大概利用快捷键Shift + F10(Mac体系是control + R)。
等程序运行完毕,点击Android Studio底部工具栏的“Android Monitor”,在Logcat中就可以看到打印信息了

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十月之后的。
下来是新版利用方法:

在绿色的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企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

民工心事

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表