为什么onAttach之前打过onCreate?

Sim*_*mon 51 android android-fragments

在Fragment的生命周期中,onAttach()方法在onCreate()方法之前调用.我无法绕过这个.你为什么要先附上片段?

Dro*_*kas 36

TL; DR:

为了不破坏 android中不同UI组件之间的设计一致性,该onCreate()方法将在所有这些组件中具有类似的功能.

将容器链接到窗口到活动和活动到片段等内容时,需要进行初步检查以确定容器的状态.这解释onAttach()了片段生命周期中的用法和位置.

太短;需要更长时间:

答案在原型代码本身,

@Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }
Run Code Online (Sandbox Code Playgroud)

另一个例子是Jake Wharton的ActionBarSherlock库.

为什么要onCreate()活动,服务中使用与其具有相同目的的方法.

onCreate()是为了处理与特定上下文创建有关的问题.如果onCreate()用于检查其容器的状态则没有意义.

我可以确定的第二个原因是片段被设计为独立于活动.onAttach()提供一个接口来确定包含活动的状态/类型/(对片段重要的其他细节)并参考您之前的片段初始化片段.

编辑:

活动独立存在,因此具有自我维持的生命周期.

对于片段:

  1. 独立的生命周期组件(与任何其他组件相同):

    • 的onCreate()
    • 在onStart()
    • 的onResume()
    • 的onPause()
    • 的onStop()
    • 的onDestroy()
  2. 基于交互的组件:

    • onAttach()
    • onCreateView()
    • onActivityCreated()
    • onDestroyView()
    • onDetach()

文件:

片段生命周期的流程,因为它受其主机活动影响,(...)活动的每个连续状态确定片段可以接收哪些回调方法.例如,当活动收到onCreate()回调时,活动中的片段只接收onActivityCreated()回调.

一旦活动达到恢复状态,您就可以自由地向活动添加和删除片段.因此,只有当活动处于恢复状态时,片段的生命周期才能独立地改变.

但是,当活动离开恢复状态时,片段再次被活动推送到其生命周期.

回答评论中提出的另一个问题:

警告:如果在Fragment中需要Context对象,则可以调用getActivity().但是,只有在片段附加到活动时才要小心调用getActivity().当片段尚未附加或在其生命周期结束时被分离时,getActivity()将返回null.

设计理念指出Fragment是为重用而设计的.片段(按设计)可以(并且应该)用于多个活动.

onCreate顾名思义就是负责创建一个片段.考虑方向的情况,您的片段可以是: - 在不同的方向使用不同的布局. - 仅适用于纵向而非横向 - 仅适用于桌子和手机.

所有这些情况都需要在从android perspective(onCreate())和视图膨胀(onCreateView())初始化片段之前进行检查.

还要考虑无头片段的情况.onAttach()为您提供初步检查所需的界面.

  • 对不起,但是我找不到这个"标记为已接受的答案"中提出的问题的答案 (2认同)

ser*_*nka 13

因为onAttach()分配托管活动Fragment.如果它之后被调用,onCreate()那么你的片段就没有上下文(getActivity()会返回null),并且如果onCreate()没有那个上下文,你将无法在方法中做任何事情.

另一个合适的原因是Fragment的生命周期类似于Activity的生命周期.在Activity.onAttach()活动中附加到其父(窗口).类似地Fragment.onAttach(),在完成任何其他初始化之前,片段将附加到其父(活动).


jsk*_*rbi 9

这与保留的片段有关.以下片段setRetainInstance(boolean retain)文档:

如果设置,则在重新创建活动时,片段生命周期会略有不同:

  • onDestroy()不会被调用(但是onDetach()仍然会被调用,因为片段正在与其当前活动分离.
  • 因为片段没有被重新创建,所以不会调用onCreate(Bundle).
  • onAttach(Activity)和onActivityCreated(Bundle)仍将被调用.

看一下源代码(android.support.v4.app.FragmentManager,v21):

void moveToState(Fragment f, 
                 int newState, 
                 int transit, 
                 int transitionStyle,
                 boolean keepActive) {
    ...
    f.onAttach(mActivity);
    if (!f.mCalled) {
        throw new SuperNotCalledException("Fragment " + f
                + " did not call through to super.onAttach()");
    }
    if (f.mParentFragment == null) {
        mActivity.onAttachFragment(f);
    }

    if (!f.mRetaining) {
        f.performCreate(f.mSavedFragmentState); // <- Here onCreate() will be called
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

情况1:未保留片段或setRetainInstanceState(false)

申请开始.片段是使用FragmentManager动态添加的,或者是通过XML扩展的setContentView().

onAttach()所谓的活动super.onCreate()通话-活动已被初始化.

MainActivity? call super.onCreate() before
MainActivity? super.onCreate() returned
MainFragment? onAttach() getActivity=com.example.MainActivity@1be4f2dd
MainFragment? onCreate() getActivity=com.example.MainActivity@1be4f2dd
Run Code Online (Sandbox Code Playgroud)

配置已更改.Activity从已保存状态重新创建片段,从Activity super.onCreate()调用内部添加/附加片段:

MainActivity? call super.onCreate() before
MainFragment? onAttach() getActivity=com.example.MainActivity@2443d905
MainFragment? onCreate() getActivity=com.example.MainActivity@2443d905
MainActivity? super.onCreate() returned
Run Code Online (Sandbox Code Playgroud)

案例2:setRetainsInstanceState(true)

申请开始.片段是使用FragmentManager动态添加的,或者是通过XML扩展的setContentView().与上述相同:

onAttach()所谓的活动super.onCreate()通话-活动已被初始化.

MainActivity? call super.onCreate() before
MainActivity? super.onCreate() returned
MainFragment? onAttach() getActivity=com.example.MainActivity@3d54a168
MainFragment? onCreate() getActivity=com.example.MainActivity@3d54a168
Run Code Online (Sandbox Code Playgroud)

配置已更改.

片段onCreate()未调用,但onAttach()仍然调用 - 您需要知道,托管活动已更改.但仍然已经创建了片段,所以没有onCreate()调用.

MainActivity? call super.onCreate() before
MainFragment? onAttach() getActivity=com.example.MainActivity@d7b283e
MainActivity? super.onCreate() returned
Run Code Online (Sandbox Code Playgroud)