回收视图如何在内部工作?

在构建Android应用程序时,我们很有可能必须在我们的项目中使用回收视图。

在这篇文章中,我们将了解回收器视图在Android系统中的实际工作方式。

我们将讨论,

  • 什么是回收视图?
  • 回收站的构建组件视图
  • 它是如何工作的?
  • 视图持有者的用法

什么是回收视图?

回收视图是一个视图组,它填充在视图持有者的帮助下提供的数据集合的列表,并将其绘制到屏幕上的用户。

回收站的构建组件视图

回收站的主要组成部分是,

  • 适配器
  • ViewHolder
  • 布局管理器

适配器

它是回收器视图类的子类型。它采用必须在回收视图中向用户显示的数据集。它就像主要的负责类来绑定视图并显示它。

大多数任务发生在回收器的适配器类中View。

ViewHolder

ViewHolder 是一种帮助程序类,可帮助我们为要在屏幕上绘制的各个项目绘制 UI。

各个项的视图的所有绑定都发生在此类中。它是回收器视图.视图持有者类的子类。

布局管理器

布局管理器 在回收器View中帮助我们弄清楚我们需要如何在屏幕上显示项目。它可以是线性的,也可以是在网格中。
默认情况下,回收视图提供了一些现成的布局管理器实现。

它就像回收商视图的管理机构,它告诉回收商View的适配器何时创建新视图。

它是如何工作的?

因此,现在我们将讨论回收器视图的实际工作原理。当我们谈论回收者视图时,您总是会听到有人说它回收了视图。但它实际上意味着什么呢?

因此,假设当我们滚动集合中包含50个项目的列表时,我们在列表中一次只显示5个项目,例如,

在这里,项目1到项目5是在屏幕上可见的那些。 是当我们向上滚动时将在屏幕上加载的下一个。item x

此处的所有项目都有自己的视图持有者实例,此处的视图持有者有助于缓存特定项目的视图。

那么,回收在这里是如何运作的呢?

让我们分步骤分解。

步骤01

第一项 x 到第 4 项必须在初始启动时显示到屏幕。因此,它们是处于可见视图模式的五个项目。让我们将它们称为可见视图。

并且,项目 5 是在向上滚动列表时要加载的新项目。

步骤02

当我们在上面滚动一个项目时,项目x向上移动,一个新项目,项目5出现在可见视图类别中。

现在,项目 6 处于等待视图中。

此处,项目 x 已从屏幕顶部的可见视图中移出。这称为报废视图。

ScrapView是回收视图中的视图,它曾经是可见的,现在对用户来说不可见在手机屏幕上。

步骤03

现在,假设我们又向上滚动了一步。这会将项目 1 移出屏幕,项目 6 将移入屏幕。

在这里,项目 1 也成为报废视图。现在,我们有两个废弃视图项 x 和项 1。

它们现在将存储在已报废视图的集合中。

因此,现在,当我们必须在可见视图组中加载新视图时,让我们考虑项目 7,然后使用已报废视图中集合中的视图。

步骤04

现在,当我们加载项目 7 时,我们从已报废的视图集合中获取视图。我们从报废视图中加载的视图称为脏视图。

现在,脏视图被回收并重新定位到队列中的新项目,该项目必须显示在屏幕上,即项目7。

我们从报废视图集合中获取的视图,然后在回收器适配器将其绘制到屏幕之前由ReplaceerView适配器重新绑定后,这些视图称为脏视图。

这就是回收视图中视图的回收方式,这是回收者视图更好改进的主要原因之一。在此过程中,将重用项目的视图以在屏幕上绘制新项目。

ViewHolder的用法

优化视图的另一种方式是因为回收视图中的ViewHolder。

因此,假设列表中显示100个项目,并且我们希望在屏幕上显示5个项目。

此处的每个项目在项目中都有 1 个文本视图和 1 个图像视图。

因此,使用 findViewById 映射每个视图始终是一项代价高昂的任务,想象一下我们可能需要映射 100 个项目(即 200 个查找视图字节)的所有文本视图和图像视图的数量。

因此,当我们使用RecysterView时,最初只创建6个项目,一次加载5个项目以显示在屏幕上,一个是要加载的项目。

现在,如果我们滚动列表,那么我们有7个ViewHolder。报废视图和待加载视图各一个,显示的视图各一个。

因此,一次最多只能有 14 个,因为我们最多有 7 个ViewHolder。

结论

由于ViewHolder和视图的回收,我们在回收视图中获得了性能改进。

同样,如果我们有多个视图类型,假设视图类型1和视图类型2,那么我们将有两个不同的报废视图集合,类型为视图类型1和视图类型2。

在回收视图时,视图类型 1 视图将仅分配给视图类型 1 的视图,并且视图类型 2 视图将分配给视图类型 2 视图。

这就是回收视图在内部高效工作的方式。

Android 中,**视图(View)从视图树(View Hierarchy)中移除**主要发生在以下场景: --- ### **1. 主动调用移除方法** - **`ViewGroup.removeView(View)`** 直接调用父容器的 `removeView()` 方法将子 View 从布局中移除: ```java ViewGroup parent = (ViewGroup) childView.getParent(); parent.removeView(childView); // 触发 onDetachedFromWindow() ``` - **`ViewGroup.removeViewAt(int)`** 通过索引移除指定位置的子 View。 - **`ViewGroup.removeAllViews()`** 清空父容器中的所有子 View。 --- ### **2. 布局替换或更新** - **动态替换布局** 例如通过 `ViewStub.inflate()`、`FragmentTransaction.replace()` 等操作,旧 View 会被移除: ```java ViewStub stub = findViewById(R.id.stub); stub.inflate(); // 原占位 View 被移除 ``` - **AdapterView 的数据更新** `ListView`/`RecyclerView` 等控件在数据变化时(如 `notifyDataSetChanged()`),部分子 View 可能被移除并回收。 --- ### **3. Activity/Fragment 销毁** - **Activity 退出** 当 Activity 调用 `finish()` 或被系统销毁时,其整个视图树会被移除,所有子 View 逐层触发 `onDetachedFromWindow()`。 - **Fragment 移除** 通过 `FragmentTransaction.remove(fragment)` 移除 Fragment 时,其关联的 View 会被移除。 --- ### **4. 对话框/弹窗关闭** - **Dialog.dismiss()** 对话框关闭时,内部的 View 会从窗口分离。 - **PopupWindow.dismiss()** 弹窗隐藏时会触发关联 View 的 `onDetachedFromWindow()`。 --- ### **5. 特殊场景** - **RecyclerView 的 Item 回收** 当 Item 滑出屏幕时,可能被 `Recycler` 回收,此时会触发 `onDetachedFromWindow()`,但后续可能重新复用(不会立即销毁)。 - **配置变更(如屏幕旋转)** Activity 重建时,旧 View 树会被移除,新 View 树重新创建。 --- ### **关键区别:`GONE` vs 移除** - **`View.GONE`** 仅设置可见性,View 仍保留在视图树中,**不会触发 `onDetachedFromWindow()`**。 - **`removeView()`** 彻底从父容器移除,**会触发 `onDetachedFromWindow()`**。 --- ### **验证方法** 可以通过重写 `onDetachedFromWindow()` 并打印日志观察触发时机: ```java @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); Log.d("TAG", "View 从窗口分离"); } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值