【问题标题】:Android - Where should findViewById be called? Activity or Fragment?Android - 应该在哪里调用 findViewById?活动还是片段?
【发布时间】:2016-02-15 09:55:51
【问题描述】:

我正在构建一个应用程序,它将支持here 提到的多种设备尺寸。

要处理 inside Fragment 的视图,可以在 Activity 的 onCreate() 或 Fragment 的 onViewCreated() 中使用 findViewById 进行查找。

它们都可以工作,因为:如果您从 Activity 执行此操作,您将处理 Fragment 父级,并且您的 View 仍将在其中,如果您从 Fragment 执行此操作,它将有正常的findViewById 行为。

所以……

  • 进行视图查找的最佳位置是什么?
  • 哪个更快?
  • 哪个效率更高?

两者各有优势:

如果您在Activity 中进行操作:

  • 您可以直接在托管 Activity 中控制用户交互(如点击监听器)。
  • 您不需要实现从 Activity 到 Fragment 的接口回调。

如果您在Fragment 中进行操作:

  • 视图在它们使用的上下文中被实例化。
  • 片段可以在同一布局中重复使用。

顺便还有this question。他们在其中讨论了使用 getViewgetActivityFragment 中调用findViewById

接受的答案是:

而不是使用 getActivity().findViewById(),你会想要 getView().findViewById()。这样做的原因是,如果您使用 视图查找的活动,那么你会遇到麻烦 多个具有相同视图 ID 的片段附加到它

但是,如果您永远不会在同一布局中重复使用 Fragment,那会是在 Activity 中进行查找的好案例吗?


示例布局:

ma​​in_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/f_main"
        class=".fragments.MainFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout="@layout/fragment_main" />

</FrameLayout>

fragment_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragments.MainFragment">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/a_main_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

您可以从ActivityFragment 访问带有id a_main_recycler 的RecyclerView

【问题讨论】:

  • To handle the views inside the Fragment one might either do the lookup with findViewById in the Activity's onCreate() or in the Fragment's onViewCreated(). 错误!要在片段中查找视图,您应该在片段中进行!

标签: android android-layout android-fragments android-activity


【解决方案1】:

支持多种设备大小与片段无关。由于其他原因,它们可能是一个好主意,但这不是重点。但是 Activity 应该永远知道片段内部的任何内容。如果是这样,你就完全错过了 Fragments 的意义,要么根本不应该拥有它们,要么应该重构你的代码。

【讨论】:

    【解决方案2】:

    findViewById 涉及遍历视图层次结构树。因此,最好从尽可能靠近您要查找的节点开始。当您在活动上执行 findViewById 时,它将调用委托给其窗口,该窗口又委托给它的 decorView,这是层次结构中的最高视图。 因此,如果您从片段视图而不是活动中执行 findViewById 会更快。

    【讨论】:

      【解决方案3】:

      TL;DR:阅读Gabe's answer

      这意味着在活动中有多个片段。

      片段是处理多种屏幕尺寸的一种技术。它们不是处理多种屏幕尺寸的必要条件。

      进行视图查找的最佳位置是什么?

      如果视图是片段的一部分(例如,片段膨胀了包含视图的布局),片段会执行 findViewById() 调用,并且片段会管理该视图(例如,注册事件侦听器)。

      如果视图位于任何片段之外(例如,直接属于 Activity 本身的 ViewPager),则 Activity 会调用 findViewById(),并由 Activity 管理该视图。

      哪个更快?哪个效率更高?

      它们应该大致相等。

      如果您在 Activity 中执行这些操作...您可以直接在托管 Activity 中控制用户交互(如点击侦听器)。

      为多种屏幕尺寸使用片段背后的意义在于,您希望有条件地使用片段。例如,在 Google 的经典主/细节 UI 设置中,活动要么显示一个片段(主),要么显示两个片段(主和细节)。其他一些活动负责显示细节。因此,管理细节的代码需要在细节片段中;否则,您在两个活动之间会有代码重复。

      如果您的 UI 始终显示相同的片段,请不要为片段而烦恼。片段是一种技术。他们不是宗教。

      但是如果你永远不会在同一个布局中重复使用 Fragment,那会是一个在 Activity 中进行查找的好案例吗?

      没有。

      您可以从 Activity 或 Fragment 访问 ID 为 a_main_recycler 的 RecyclerView。

      仅当片段存在时。在这种情况下,您使用的是静态片段,因此它始终存在。不是所有的片段都会。

      【讨论】:

        【解决方案4】:

        绝对在 Fragment 中,如果视图与 Fragment 相关,最好使用 Fragment 中的实例化。这就是 Fragment 分割视图/屏幕/布局的主要目的。

        片段在生命周期中存在,因此视图是使用片段创建和销毁的。

        如果相同的视图将出现在屏幕上,则在 Activity 中实例化,无论您在那里显示哪个片段。

        通俗地说> 将Activity视为星巴克的总部,将碎片视为星巴克的不同门店,您的问题是您应该在哪里卖咖啡!

        编辑:-阅读CommonsWare's answer了解详情。 :)

        【讨论】:

          猜你喜欢
          • 2013-10-31
          • 1970-01-01
          • 1970-01-01
          • 2020-09-22
          • 2015-06-06
          • 1970-01-01
          • 1970-01-01
          • 2012-09-20
          • 1970-01-01
          相关资源
          最近更新 更多