【问题标题】:Android Fragment onAttach() deprecatedAndroid Fragment onAttach() 已弃用
【发布时间】:2015-11-12 00:26:18
【问题描述】:

我更新了我的应用程序以使用最新的支持库(版本 23.0.0),我发现他们弃用了 Fragment 类的 onAttach() 函数。

代替:

onAttach (Activity activity)

现在是:

onAttach (Context context)

由于我的应用程序使用在弃用之前传递的活动,我认为一个可能的解决方案是:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    activity = getActivity();
}

这是正确的做法吗?

更新:

如果我运行 API 低于 23 的设备,甚至不会调用新的 onAttach()。我希望这不是他们打算做的!

更新 2:

问题已通过 SDK 的最新更新解决。

我已经在我的 API 22 设备上进行了测试,并且正在调用 onAttach(Context)。

点击here 关注我几周前打开的错误报告以及 Google 员工的回答。

【问题讨论】:

  • 如果您在传递的实例中使用特定的 Activity 方法,那么您是否尝试将上下文转换为您的 Activity?记住 Activity 是 Context 的子类。也许铸造会起作用。
  • 由于某种原因,onAttach() 甚至没有被调用!有任何想法吗?您是否尝试更新到最新的支持库。
  • 为什么 API 已移至 Context?无论如何,您不需要Activity 来附加和显示片段吗?否则您将如何使用Context 参数?
  • 我已经把它作为一个bug发布了,见链接code.google.com/p/android/issues/detail?id=183358
  • 要调用新的onAttach(Context context),您需要使用至少具有 API 23 的设备或使用 android.support.v4.app.Fragment。见here

标签: android android-fragments


【解决方案1】:

Activity 是一个上下文,所以如果您可以简单地检查上下文是一个 Activity 并在必要时进行转换。

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    Activity a;

    if (context instanceof Activity){
        a=(Activity) context;
    }

}

更新:有些人声称从未调用过新的 Context 覆盖。我已经做了一些测试,但找不到这样的场景,根据源代码,它永远不应该是真的。在我测试的所有情况下,SDK23 之前和之后,ActivityContext 版本的onAttach 都被调用了。如果你能找到一个不是这种情况的场景,我建议你创建一个示例项目来说明这个问题和report it to the Android team

更新 2:我只使用 Android 支持库片段,因为那里的错误得到更快地修复。似乎只有在您使用框架片段时才会出现上述覆盖未正确调用的问题。

【讨论】:

  • 不是真正的解决方案,因为 onAttach with context 与 onAttach with activity 的调用方式不同。如果您在 onAttach 中有一些初始化代码,并将活动作为参数,则此更改将不起作用。
  • 不,它不一样,至少在我的情况下。我在 onAttach 中不使用活动或上下文,我进行初始化。我尝试将 onAttach 替换为带有上下文的活动,但它不会以相同的方式被调用。所以它们不是那么容易互换的。
  • Buddy 有同样的问题...onAttach(Context) 似乎没有被调用。
  • 我已单步执行我的代码,我可以验证onAttach(context) 是否可能不会被调用。
  • 在我的情况下,如果我们重新启动之前被系统清除的活动,则不会调用 onAttach()。但并不总是这样。我在 onAttach(Context context), refActivity = new WeakReference((AppCompatActivity) context) 中放置了 WeakReference 的初始化。它偶尔会在 onCreateView() 中抛出 NullPointerException。
【解决方案2】:

这是 Google 的另一个重大变化...建议的修改:将 onAttach(Activity activity) 替换为 onAttach(Context context) 会导致我的应用在旧 API 上崩溃,因为不会在原生片段上调用 ​​onAttach(Context context)

我正在使用本机片段 (android.app.Fragment),因此我必须执行以下操作才能使其在旧 API (

这是我所做的:

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    // Code here
}

@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        // Code here
    }
}

【讨论】:

  • Mr.Yoann Hercouet,您能解释一下如何在 API 23 上执行此操作,请帮助我,在此先感谢,E/AndroidRuntime: FATAL EXCEPTION: main, java.lang.ClassCastException: com.ual .SMS_Activity@afd5683,在 android.support.v4.app.FragmentManagerImpl.moveToState,在 android.support.v4.app.FragmentManagerImpl.execSingleAction。在这里,我发布了必要的行,您可以了解我的错误。
  • @MohanRajS 在API 24(我使用的那个)上也是一样的,根据你的一段代码,你的问题似乎与此无关。
  • @YoannHercouet ,感谢您的回复,让我检查并更新。
  • 您对 Google 对此不满意,因为难以针对较旧的 API。好吧,考虑一下您可以针对较旧的 API 的好处,而 Apple 会极大地削弱您并迫使您仅支持最新的 API。
【解决方案3】:

如果您使用框架片段并且设备的SDK版本低于23,则不会调用OnAttach(Context context)

我改用支持片段,所以弃用是固定的,onAttach(Context context) 总是被调用。

【讨论】:

    【解决方案4】:

    目前来自onAttach的Fragment代码,不清楚Context是否是当前活动:源码

    public void onAttach(Context context) {
        mCalled = true;
        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
        if (hostActivity != null) {
            mCalled = false;
            onAttach(hostActivity);
        }
    }
    

    如果您查看getActivity,您会看到相同的调用

    /**
     * Return the Activity this fragment is currently associated with.
     */
    final public Activity getActivity() {
        return mHost == null ? null : mHost.getActivity();
    }
    

    因此,如果您想确定您正在获取活动,请使用getActivity()(在您的onAttach 中的Fragment)但不要忘记检查null,因为如果mHost 是@ 987654331@您的活动将是null

    【讨论】:

      【解决方案5】:
      @Override
      public void onAttach(Context context) {
          super.onAttach(context);
      
          Activity activity = context instanceof Activity ? (Activity) context : null;
      }
      

      【讨论】:

        【解决方案6】:

        虽然看起来在大多数情况下拥有onAttach(Context) 就足够了,但也有一些手机(例如:小米 Redme Note 2)没有被调用,因此会导致 NullPointerExceptions。因此,为了安全起见,我建议也不要使用已弃用的方法:

        // onAttach(Activity) is necessary in some Xiaomi phones
        @SuppressWarnings("deprecation")
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            _onAttach(activity);
        }
        
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            _onAttach(context);
        }
        
        private void _onAttach(Context context) {
            // do your real stuff here
        }
        

        【讨论】:

          【解决方案7】:

          使用 sdk 管理器下载最新的支持库并包含

          compile 'com.android.support:appcompat-v7:23.1.1'
          

          在 gradle.app 中并将编译版本设置为 api 23

          【讨论】:

            【解决方案8】:

            下面的答案与 Android 开发者网站上的 Fragments 教程中出现的弃用警告有关,可能与上面的帖子无关。

            我在教程课程中使用了这段代码,它确实有效。

            public void onAttach(Context context){
                super.onAttach(context);
            
                Activity activity = getActivity();
            

            我担心活动可能如文档所述为空。

            获取活动

            FragmentActivity getActivity() 返回此片段当前关联的 FragmentActivity。如果片段与上下文相关联,则可能返回 null。

            但是main_activity上的onCreate清楚地表明fragment已经加载了,所以在这个方法之后,从fragment调用get activity会返回main_activity类。

            getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit();

            我希望我是正确的。我是一个绝对的新手。

            【讨论】:

              【解决方案9】:

              您可能正在使用android.support.v4.app.Fragment。为此而不是onAttach 方法,只需使用getActivity() 来获取与片段关联的FragmentActivity。否则你可以使用onAttach(Context context) 方法。

              【讨论】:

                【解决方案10】:

                当我有用户定义的接口“TopSectionListener”时,这对我有用,它的对象 activitycommander:

                  //This method gets called whenever we attach fragment to the activity
                @Override
                public void onAttach(Context context) {
                    super.onAttach(context);
                    Activity a=getActivity();
                    try {
                        if(context instanceof Activity)
                           this.activitycommander=(TopSectionListener)a;
                    }catch (ClassCastException e){
                        throw new ClassCastException(a.toString());}
                
                }
                

                【讨论】:

                • 宝贝回归你的可爱,不然我就喝,不然我就喝...
                猜你喜欢
                • 1970-01-01
                • 2023-03-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-10-25
                • 2012-12-25
                • 2021-08-31
                相关资源
                最近更新 更多