java.lang.illegalstateexception: a factory has already been set on this layoutinflater

自闭症网瘾萝莉.ら 提交于 2019-11-27 23:52:44

There been a change in support library since version 22.1.0.

You will get an IllegalStateException if you try to call getLayoutInflater().setFactory()

You should use the new api

Or simply use the old version

  • com.android.support:appcompat-v7:22.0.0
  • com.android.support:appcompat-v4:22.0.0

To keep compatibility library working and avoid "java.lang.illegalstateexception: a factory has already been set on this layoutinflater", you need to get a final reference to the already set Factory and call its onCreateView within your own Factory.onCreateView. Before that an introspection trick must be use to allow you to set one more time a Factory to the LayoutInflater :

LayoutInflater layoutInflater = getLayoutInflater();
final Factory existingFactory = layoutInflater.getFactory();
// use introspection to allow a new Factory to be set
try {
    Field field = LayoutInflater.class.getDeclaredField("mFactorySet");
    field.setAccessible(true);
    field.setBoolean(layoutInflater, false);
    getLayoutInflater().setFactory(new Factory() {
        @Override
        public View onCreateView(String name, final Context context, AttributeSet attrs) {
            View view = null;
            // if a factory was already set, we use the returned view
            if (existingFactory != null) {
                view = existingFactory.onCreateView(name, context, attrs);
            }
            // do whatever you want with the null or non-null view
            // such as expanding 'IconMenuItemView' and changing its style
            // or anything else...
            // and return the view
            return view;
        }
    });
} catch (NoSuchFieldException e) {
    // ...
} catch (IllegalArgumentException e) {
    // ...
} catch (IllegalAccessException e) {
    // ...
}

This happens because you are using compatibility library. It sets own Factory to deal with platform specific layouts. You may try to set own factory in onCreate() method before calling super.onCreate(). This will disallow compatibility library to override factory and you will be unable to inflate fragments from xml files, but styling should work.

This works for me:

LayoutInflater inflater = LayoutInflater.from(context);
if (inflater.getFactory() != null) {
    inflater = inflater.cloneInContext(context);
}
inflater.setFactory(factory);

I faced the same issue but no answer helped me.

In my case:

  • I'm extending AppCompatActivity

  • Project targeting API 27

  • Implementation support lib 27.1.1

Solution: Apparently, now there is no need of setting the Factory to the LayoutInflater, it would crash or be ignored. Just override both methods onCreateView(...) in your AppCompatActivity (from android.support.v4.app.BaseFragmentActivityApi14)

public class myActivity extends AppCompatActivity  {
    ...
    @Override
    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
        if (name.compareTo("EditText") == 0) {
            CustomEdit newEdit = new CustomEdit(this,attrs); 
            return newEdit;
        }
        return super.onCreateView(parent, name, context, attrs);
    }
    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        return onCreateView(null, name, context, attrs);
    }
    ...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!