找视图
Find View by Id
R 类中有个名为layout的子类,其中包含了布局资源,还包含了构成用户界面的视图 findViewById()
TextView textView = findViewById(R.id.example_text);
textView.setText("demo");
其中就需要R类进行id的查找 findViewById()方法的的最大缺点是,可能获得一个内部没有创建布局的视图的引用,导致出现尝试访问视图的属性产生空指针异常的问题。
View Binding
build.gradle 中通过 buildFeatures 开启 viewBinding
android {
namespace 'com.example.basepractice'
compileSdk 34
defaultConfig {
applicationId "com.example.basepractice"
minSdk 24
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildFeatures {
viewBinding true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
} compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
基本使用
public class MainActivity extends AppCompatActivity {
public ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
binding.exampleText.setText("demo");
}
}
这种方式是先进行 binding 的创建 XXXBinding.inflate(getLayoutInflater()) 获取整个布局,根视图通过 getRoot 方法获取。
之后通过 binding 就可以根据 id 获取创建好的布局 ,没有id的就不显示组件,有效避免了,由于没创建或者写错导致空指针异常的问题。
Activity的生命周期
Android应用程序和资源管理
每一个正在运行的 Android 应用程序会被操作系统视为一个独立的进程,一但系统识别到资源达到了设备的上限,那么将会终止进程去释放资源。
当决定终止进程去释放内存,系统会考虑当前所有正在运行进程优先级和状态组成重要层级,然后终止优先级最低的进程一直往上执行,直到释放出足够的资源供系统运行。
Android进程状态
进程承载应用,由应用程序组件构成。在Android系统内部,一个进程的状态由应用程序内部承载优先级最高的活动组件决定。
Android进程状态有5种,其由高到低优先级排序如下
前台进程
前台进程是最高优先级,在任何时候都不会有 1 或者 2 个前台进程处于活跃,并且他们最后通常都会被系统终止
进程必须满足至少一个条件才能进入前台状态。
1、承载一个用户正在交互的一个 Activity。
2、承载一个用户正在交互连接到 Activity 的服务。
3、承载一个服务,通过 startForeground() 方法调用,终止就会破坏用户体验性。
4、承载一个服务,正在执行 onCreate(), onResume() or onStart() 其中任何一个回调方法。
5、承载一个正在执行 onReceive() 方法的广播接收者。
可视进程
可视进程:是一个进程包含一个可被用户看见的 Activity ,但是没有和用户产生交互的 Activity ,这个进程被称为可视进程(如Dialog浮窗之类)
服务进程
进程包含一个服务,服务已开启并且执行,就是服务进程。
后台进程
一个进程包含一个或者多个用户当前不可见的 Activity 并且也没有承载一个有效的服务进程状态的服务,一但需要释放更多的内存去执行优先级更高的进程,进程就会进入被终止的高风险分类。
Android 持有一个动态的后台进程列表,这个列表根据时间顺序排列,列表中最近最少进入前台的进程,会第一个被杀掉。
空进程
空进程不再包含任何活跃的应用程序,并且在内存中被持有为最近新运行的应用程序服务,这类进程优先级最低,首先被杀死释放资源。
Activity栈
每一个正在 Android 设备上运行的应用程序,运行时机制都会持有一个 Activity 栈,当一个应用程序是运行的,会把应用程序的第一个被开启的 Activity 压入这个栈中。
当第二个 Activity 开启后也会压入栈中,栈顶的 Activity 指的是当前正在运行的 Activity 。
当活跃的 Activity 退出,通过运行时弹出,位于其下面的 Activity 变成活跃的 Activity 。
Activity的状态
活跃状态:位于栈顶的 Activity 处于前台状态,与用户交互。
暂停状态:Activity 处于可视状态但是当前并没有交互,暂停的 Activity 被持有在内存中,保持附加的窗口管理器,保存状态信息并且当移动到栈顶时可以快速恢复到活跃状态。
停止状态:当前 Activity 用户不可见,随着暂停 Activity Activity 持有所有状态信息和成员信息,但是在低内存情况下,有着较高风险被终止。
被干掉状态:Activity 已经被系统运行时为了释放内存终止了,并且不再存在 Activity 栈中。这种 Activity 如果应用程序需要使用,必须要把 Activity 重启。
处理生命周期
Activity 和 Fragment 类
在应用程序中 Activity 和 Fragment 都是分别作为 Android 的 AppCompatActivity 和 Fragment 的子类被创建。
Activity 和 Fragment 类包含一系列用于被 Android 运行时调用去通知对象,状态正在改变。
动态状态和持续状态
由于状态信息持续的方法的一次调用到另一次调用,所以是持续状态。
用户通过界面进行输入,但没有进行提交的,状态只被持有在一次方法调用的期间,这种状态称为:动态状态。
管理生命周期的关键目标是确保 Activity 的状态的保存和合适的时机重启,当讨论状态在上下文中意味着数据正在被 Activity 内部持有并且对外呈现到用户界面。
保存持续状态的目的是避免数据丢失,这个数据可能由于 Activity 在后台运行时被运行时系统终止导致丢失。
Android 的生命周期方法
onCreate(Bundle savedInstanceState) 方法:会在 Activity 第一次被创建时调用并且是最理想的执行初始化任务的位置,这个方法要被传入一个表单中 Bundle 对象参数,这个 Bundle 对象包含动态状态信息。
onRestart() 方法:当被运行时系统停止的 Activity 重启时调用。
onStart() 方法:在 onCreate() 或 onRestart() 方法调用之后,立即被调用,这个方法表示 Activity 变为用户可视 Activity ,这个方法调用之后如果 Activity 移动到了 Activity 栈的上层,则调用 onResume() 方法,如果被其他的 Activity 压到栈底则调用 onStop() 方法。
onResume() 方法:表示 Activity 现在位于 Activity 栈顶并且用户正在和这个 Activity 进行交互。
onPause() 方法:表示上一个 Activity 变成前台 Activity 。这个方法被调用在 onResume() 或者 onStop() 之后,取决于 Activity 是否变为前台,或者变为用户不可见。可以进行没有持久化的状态保存,为了避免切换 Activity 的延迟,应该避免执行耗时操作如存储数据到数据库,或者网络请求操作。这个方法应该确保任何 CPU 密集型任务都被停止。
onStop() 方法:这个 Activity 现在不再对用户可见。可能会出现两种情况,调用 onRestart() 方法 Activity 会重新回到前台,调用 onDestroy() 方法 Activity 会被终止。
onDestroy() 方法:Activity 将被销毁,要么是 Activity 完成了任务并且调用了 finish() 方法,要么是因为运行时为了释放内存而终止或者是由于配置改变了。
onConfigurationChanged() 方法:当配置发生改变时调用,Activity 表示已经不需要重启。
以下是只应用在 Fragment 上的生命周期方法
onAttach() 方法:当 Fragment 被分配到一个 Activity 上被调用。
onCreateView() 方法:调用后创建并返回用户界面布局视图的层级。
onViewCreated() 方法:在 onCreateView() 返回之后被调用。
onViewStatusRestored() 方法:用于 Fragment 保存视图的层级。
以下是保存和恢复动态状态的方法
onRestoreInstanceState(Bundle savedInstanceState) 方法:如果 Activity 正从先前保存状态的调用中重启,此方法会在调用 onStart () 方法之后立即被调用。正如 onCreate() 这个方法传递了一个包含之前状态数据的 Bundle 类型的对象。这种方法通常用于以下情形:在onCreate()和onStart()中完成Activity 初始化后,恢复先前状态。
onSaveInstanceState(Bundle outState) 方法:在 Activity 被销毁前调用,为了保存当前的动态状态。当 Activity 被重启时,这个方法被传递一个 Bundle 类型的对象,状态会被保存到这个对象中,随后这个对象被传入 onCreate() 方法 和 onRestoreInstanceState() 方法。
流程图串起来如下
程序第一次进入 Activity
程序进入后台
程序返回前台
这两个方法的测试
由于版本不同,Android 应用程序进入后台 Activity 的处理并不相同,测试 onRestoreInstanceState 方法可以通过旋转屏幕方向来实现。
注意:保存状态是一个参数的保存状态方法,按 Home 键即可测试效果。