无法实例化Fragment

问题描述 投票:0回答:14

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

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

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

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

android android-fragments
14个回答
26
投票

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

如果你的fragment是内部类,那么它必须是静态内部类。理想情况下,它是一个独立的公共 Java 类。

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

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

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

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


16
投票

你的片段不应该有构造函数(参见本文档及其示例)。

你应该定义一个

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
    //...
}

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


11
投票

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

findViewById
工作。建议:

使用

onCreateView
中膨胀的视图,

inflatedView.findViewById(.....)

或在

onActivityCreated(.....)

中调用它
getActivity().findViewById(......)

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


4
投票

我也有这个问题 - 原来它变得很困惑,因为我的自定义 Fragment 有一个构造函数。

我重命名了构造函数方法并在实例化时调用了新方法,它成功了!


4
投票
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());
            }
 }

3
投票

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

public static class MyDialogFragment extends DialogFragment {

    public MyDialogFragment(){
    }
...
}

2
投票

使用 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)


2
投票

哈哈,我的搞笑问题是我在我的片段中调用了

getString()
作为成员级别变量,这是一个很大的禁忌,因为我想现在还为时过早。我希望错误更具描述性!


1
投票

如果你不想让内部类静态化,尝试像这样重写对话框片段的onPause方法:

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

所以当应用程序继续暂停时应该销毁片段并且没有例外。我试过了并且有效。


0
投票

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


0
投票

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


0
投票

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

必须全班名


0
投票

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


0
投票

我的错误之一是甚至在调用 onCreate 之前就从安全参数为全局变量赋值,而参数的类型可以为空。我将它移至 onCreate 并且崩溃消失了

© www.soinside.com 2019 - 2024. All rights reserved.