【问题标题】:Unable to instantiate Fragment无法实例化片段
【发布时间】:2011-08-10 19:30:38
【问题描述】:

无法实例化片段确保类名存在,是公共的, 并且有一个公开的空构造函数

是不是因为我的 Fragment 不是静态类? 是不是因为我的 Fragment 是一个内部类?

如果我将 Fragment 设为静态类,我对 findViewById 的所有引用都会失败,这意味着需要进行大量重构。

如何在不将内部 Fragment 变为静态类的情况下解决此问题?

【问题讨论】:

  • 你想解决什么问题?
  • @PJL 答案自己说话
  • 是的,干得好。好的,代表我的措辞不好的评论,但是嘿嘿!

标签: android android-fragments


【解决方案1】:

是不是因为我的 Fragment 是一个内部类

如果您的片段是内部类,则它必须是静态内部类。理想情况下,它是一个独立的公共 Java 类。

如果我将 Fragment 设为静态类,我对 findViewById 的所有引用都会失败,这意味着需要进行大量重构

无论如何,您都需要进行重构。小部件现在由片段拥有,而不是活动。片段应该尽可能少地了解包含它们的活动,以便它们可以根据需要在不同的活动之间移动以支持手机、平板电脑、电视等。

如何在不将我的内部 Fragment 变成静态类的情况下解决这个问题??

你让它成为一个独立的公共 Java 类。

【讨论】:

    【解决方案2】:

    您的 Fragment 不应该有构造函数(参见 this documentation 及其示例)。

    您应该定义一个newInstance() 静态方法并通过参数(包)传递任何参数

    例如:

    public static final MyFragment newInstance(int title, String message)
    {
        MyFragment fragment = new MyFragment();
        Bundle bundle = new Bundle(2);
        bundle.putInt(EXTRA_TITLE, title);
        bundle.putString(EXTRA_MESSAGE, message);
        fragment.setArguments(bundle);
        return fragment ;
    }
    

    并在 onCreate 阅读这些参数:

    @Override
    public Dialog onCreate(Bundle savedInstanceState)
    {
        title = getArguments().getInt(EXTRA_TITLE);
        message = getArguments().getString(EXTRA_MESSAGE);
    
        //...
        //etc
        //...
    }
    

    这样,如果分离并重新附加,对象状态可以通过参数存储,就像附加到 Intent 的捆绑包一样。

    【讨论】:

    • 是的,最佳答案一英里...干杯老兄,这真的帮助我掌握了片段的整个概念。 +1
    • 创建一个具有相同参数类型(此处为空)的新 CTOR 应该没问题,这样无论框架做什么,它都会被使用。不?文档只讨论带参数的 CTOR。空的应该还是可以的,因为你可能想要初始化一些东西(比如对单例和一些监听器的引用)。
    【解决方案3】:

    正如 CommonsWare 所说的让它成为静态或独立的,另外不知道为什么你需要大量的重构来让findViewById 工作。建议:

    使用onCreateView中膨胀的视图,

    inflatedView.findViewById(.....)
    

    或在onActivityCreated(.....)调用它

    getActivity().findViewById(......)
    

    但是,即使您仍然需要大量重构,那么可能就是这样,将应用程序转换为使用片段并不是免费的,因为刚刚完成了一个项目。

    【讨论】:

      【解决方案4】:

      我也遇到过这个问题 - 事实证明它很困惑,因为我的自定义 Fragment 有一个构造函数。

      我重命名了构造方法,并在实例化时调用了新方法,它起作用了!

      【讨论】:

        【解决方案5】:
        public static class MyDialogFragment extends DialogFragment {
        
            public MyDialogFragment(){
        
            }
        
            public Dialog onCreateDialog(Bundle savedInstanceState) {
                    LinearLayout main = new LinearLayout(getActivity());
            main.setOrientation(LinearLayout.VERTICAL);
        
        
                    return (new AlertDialog.Builder(getActivity()).setTitle(
            getText("Title")).setView(main).create());
                    }
         }
        

        【讨论】:

          【解决方案6】:

          就我而言,我缺少构造函数,上面@eoghanm 的帖子帮助了我

          public static class MyDialogFragment extends DialogFragment {
          
              public MyDialogFragment(){
              }
          ...
          }
          

          【讨论】:

          • 仅供参考,无需再次发布相同的答案。如果 eoghanm 的回答是正确的,请检查它旁边的复选标记,而不是重新发布他的建议。
          • 帖子本身并没有指向问题,我只是强调了对我来说有问题的部分。下次我会努力做得更好。
          【解决方案7】:

          使用setRetainInstance(true) 为我们工作。我们的内部类现在看起来像这样:

          public class SectionsPagerAdapter extends FragmentPagerAdapter {
              public SectionsPagerAdapter(FragmentManager fm) {
                  super(fm);
              }
          
              @Override
              public Fragment getItem(int position) {
              // getItem is called to instantiate the fragment for the given page.
                  Fragment fragment = new MySectionFragment();
                  Bundle args = new Bundle();
                  args.putInt(MySectionFragment.ARG_SECTION_NUMBER, position + 1);
                  fragment.setArguments(args);
                  fragment.setRetainInstance(true);
                  return fragment;
              }
              // ...
          }
          
          public class MySectionFragment extends Fragment {
              public static final String ARG_SECTION_NUMBER = "section_number";
              @SuppressLint("ValidFragment")
              public MySectionFragment() {
              }
              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  //...
              }       
              // ...
          }
          

          附言。这里有一个关于 setRetainInstance(boolean) 的有趣内容:Understanding Fragment's setRetainInstance(boolean)

          【讨论】:

            【解决方案8】:

            如果你不想让内部类变成静态的,试着像这样覆盖对话框片段的onPause方法:

            public void onPause()
            {
              super.onPause();
              dismiss();
            }
            

            所以当应用程序暂停并且没有异常时应该销毁片段。我试过了,效果很好。

            【讨论】:

              【解决方案9】:

              哈哈,我的搞笑问题是我调用了 getString() 作为我片段中的成员级别变量,这是一个很大的不,因为我想现在还为时过早。我希望错误更具描述性!

              【讨论】:

                【解决方案10】:

                确保片段不是抽象的。复制和粘贴使这种事情发生:(

                【讨论】:

                  【解决方案11】:

                  内部类构造函数必须传入外部类的实例。所以据说编译器找不到没有参数的构造函数。所以应该放在其他java文件的静态中。

                  【讨论】:

                    【解决方案12】:

                    我遇到了这个问题 你需要使用完整的类名: 例如: Fragment.instantiate(MainActivity.this, com.XX.yourFragmentName);

                    必须是全类名

                    【讨论】:

                      【解决方案13】:

                      还值得尝试检查您的默认 Fragment 构造函数是 public,而不是 Android Studio 可能建议的 package-private。这就是我的原因。

                      【讨论】:

                        猜你喜欢
                        • 2015-05-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2021-05-04
                        相关资源
                        最近更新 更多