Android - 应该在哪里调用findViewById?活动还是片段?

时间:2016-02-11 22:13:23

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

我正在构建一个支持多种设备尺寸的应用程序here

要处理内部的视图,Fragment可能会在活动onCreate()或片段&#中使用findViewById进行查找。 39; s onViewCreated()

他们都会工作,因为:如果你从Activity执行此操作,那么您将处理Fragment父母,并且您的View仍将在其中,如果您从Fragment开始,它会有正常的findViewById行为。

所以......

  • 查看查找的最佳位置是什么?
  • 哪一个更快?
  • 哪一个效率更高?

他们都有自己的优势:

如果您在Activity

中执行此操作
  • 您可以在托管活动中控制用户互动(例如点击监听器)。
  • 您不需要实现从Activity到Fragment的接口回调。

如果您在Fragment

中执行此操作
  • 视图在上下文中被实例化。
  • 碎片可以在相同的布局中重复使用。

顺便提一下this question。他们在讨论使用 getView getActivity 来调用findViewById中的Fragment

接受的答案是:

  

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

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

示例布局:

main_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>

您可以通过RecyclerViewActivity访问ID为a_main_recycler的Fragment

4 个答案:

答案 0 :(得分:6)

支持多种设备大小与片段无关。出于其他原因,它们可能是一个好主意,但除此之外。但是一个Activity应该从不知道片段内部的内容。如果确实如此,那么你完全错过了Fragments的观点,要么根本不应该有它们,要么重构你的代码。

答案 1 :(得分:1)

findViewById涉及遍历视图层次结构树。因此,最好尽可能靠近您正在寻找的节点。当你在一个活动上找到ViewById时,它会将调用委托给它的窗口,窗口又委托给它的decorView,它是层次结构中的最高视图。    因此,如果从片段视图而不是活动中找到FindViewById,它会更快。

答案 2 :(得分:1)

TL; DR:阅读Gabe's answer

  

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

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

  

查看查找的最佳位置是什么?

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

如果视图位于任何片段之外(例如,直接属于活动本身的ViewPager),则活动执行findViewById()调用,活动将管理该视图。 / p>

  

哪一个更快?哪一个更有效率?

他们应该大致相同。

  

如果您在活动中执行此操作...您可以在托管活动中控制用户交互(例如点击监听器)。

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

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

  

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

没有

  

您可以从活动或片段中访问带有id a_main_recycler的RecyclerView。

只有片段在那里。在这种情况下,您使用的是静态片段,因此始终存在。并非所有碎片都是。

答案 3 :(得分:0)

绝对在Fragment中,如果视图与片段相关,则更好地使用片段中的实例化。这就是Fragment对视图/屏幕/布局进行分段的主要目的。

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

如果在屏幕上显示相同的视图,则在“活动”中实例化,无论您在那里显示哪个片段。

以非专业人士的身份&gt;将活动视为星巴克的总部,并将其分解为星巴克的不同渠道,您的问题是您应该在哪里卖咖啡!!

修改: - 阅读CommonsWare's answer了解详细信息。 :)