开发者

Unable to instantiate Fragment

开发者 https://www.devze.com 2023-03-27 18:47 出处:网络
Unable to instantiate fragment make sure class name exists, is public, and has an empty constructor that is public

Unable to instantiate fragment make sure class name exists, is public, and has an empty constructor that is public

Is it because my Fragment is not a static class? Is it because my Fragment is an inner class?

If I make my Fragment a static class, all my开发者_如何学C references to findViewById fail, which means a LOT of refactoring.

How can I solve this without turning my inner Fragment into a static class?


is it because my Fragment is an inner class

If your fragment is an inner class, it must be a static inner class. Ideally, it's a standalone public Java class.

if I make my Fragment a static class, all my references to findViewById fail, which means a LOT of refactoring

You needed to do that refactoring anyway. Widgets are now owned by the fragment, not the activity. Fragments should know as little as possible about what activity contains them, so they can be shuffled between different activities as needed to support phones, tablets, TV, etc.

How can I solve this without turning my inner Fragment into a static class??

You make it a standalone public Java class.


Your Fragment shouldn't have constructors (see this documentation and its examples).

You should have a newInstance() static method defined and pass any parameters via arguments (bundle)

For example:

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 ;
}

And read these arguments at onCreate:

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

    //...
    //etc
    //...
}

This way if detached and re-attached the object state can be stored through the arguments, much like bundles attached to Intents.


As CommonsWare said make it static or standalone, additionally don't know why you need a shedload of refactoring for getting findViewById to work. Suggestions:

Using the view inflated in onCreateView,

inflatedView.findViewById(.....)

or calling it in onActivityCreated(.....)

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

But even if you still need a load of refactoring then that might just be the way it is, converting an app to use fragments doesn't come for free having just finished a project doing so.


I had this problem as well - turns out it was getting confused because my custom Fragment had a constructor.

I renamed the constructor method and called the new method instead upon instantiation, and it worked!


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


In my case, I was missing the constructor, the post from @eoghanm above helped me

public static class MyDialogFragment extends DialogFragment {

    public MyDialogFragment(){
    }
...
}


Using setRetainInstance(true) worked for us. Our inner classes now look like this:

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

PS. Here's an interesting one about setRetainInstance(boolean): Understanding Fragment's setRetainInstance(boolean)


if you don't want to make the inner class static, try to override the method onPause of the dialog fragment like this:

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

so the fragment should be destroyed when the app goes on pause and there is no exception. i tried it and works.


Hahah my hilarious issue was I had a call to getString() as a member level variable in my fragment which is a big no no because it's too early I guess. I wish the error was more descriptive!


Make sure the Fragment isn't abstract. Copy&paste makes this kind of things happen :(


The inner class constructor must be pass in an instance of the outer class. so it is said the compiler cannot find the constructor which has no parameter. so it should be put into static of other java file.


i have meet this problem you need use full class name : eg: Fragment.instantiate(MainActivity.this, com.XX.yourFragmentName);

must full class name


It is also worth trying to check that your default Fragment constructor is public, not package-private, which Android Studio might propose. This was the cause in my case.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号