it-roy-ru.com

Фрагмент должен быть общедоступным статическим классом, чтобы он был правильно воссоздан из состояния экземпляра.

После обновления до последнего репозитория поддержки, 

compile 'com.Android.support:appcompat-v7:24.2.0'
compile 'com.Android.support:design:24.2.0'
compile 'com.Android.support:percent:24.2.0'
compile 'com.Android.support:recyclerview-v7:24.2.0'

Я получаю странное исключение.

Java.lang.IllegalStateException: Fragment null must be a public static class to be  properly recreated from instance state.
at Android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.Java:435)
at Android.support.v4.app.BackStackRecord.add(BackStackRecord.Java:414)
at Android.support.v4.app.DialogFragment.show(DialogFragment.Java:154)
at com.androidapp.base.BaseActivity.showDialogFragment(BaseActivity.Java:78)
at com.androidapp.MainActivity.showNewDialog(MainActivity.Java:304)
at com.androidapp.MainActivity$6.onClick(MainActivity.Java:228)

В моем BaseActivity class я создал фрагмент многократного использования, который можно использовать в классе активности, который расширяет BaseActivty

public void showDialogFragment(DialogFragment newFragment) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
        if (prev != null) {
            ft.remove(prev);
        }
        ft.addToBackStack("dialog");
        newFragment.show(ft, "dialog");
    }

Вернуться к MainActivty Я использовал такой фрагмент,

public class MainActivity extends BaseActivity {

    @SuppressLint("ValidFragment")
        public void showNewDialog(int type, String title, String message) {
            final DialogNew dialog = new DialogNew() {
                @Override
                public void success(boolean isLandscape) {
                    .......
                }

                @Override
                public void cancel() {

                }
            };
            dialog.setArgs(title, message);
            super.showDialogFragment(dialog);
        }
}

DialogNew класс ниже,

public abstract class DialogNew extends DialogFragment {

    private View rootView;

    private String title;
    private String message;

    public void setArgs(String title, String message) {
        Bundle args = new Bundle();
        args.putString("title", title);
        args.putString("message", message);
        setArguments(args);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NO_TITLE, 0);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        rootView = inflater.inflate(R.layout.fragment_new_dialog, container, false);

        init();
        setListeners();

        return rootView;
    }

    public abstract void success(boolean isLandscape);

    public abstract void cancel();
}

PS: тот же код работает со старым репозиторием поддержки. 

14
Falling Into Infinity

Ошибка не особенно странная. Если вы не получили эту ошибку раньше, это было странно.

Android уничтожает и воссоздает фрагменты как часть изменения конфигурации (например, поворот экрана) и как часть перестройки задачи, если это необходимо (например, пользователь переключается на другое приложение, процесс вашего приложения завершается, пока он находится в фоновом режиме, а затем пользователь пытается вернуться к вашему приложению, все в течение 30 минут или около того). В Android нет средств для воссоздания анонимного подкласса DialogNew.

Итак, создайте обычный класс public Java (или вложенный класс publicstatic), который расширяет DialogNew и содержит вашу бизнес-логику, заменив анонимный подкласс DialogNew, который вы используете в настоящее время.

12
CommonsWare

Редактировать: Вы, вероятно, не хотите делать это ... Смотрите комментарии.

Пример кода выглядит аналогично тому, что я предложил над здесь , и я также недавно обнаружил, что решение, которое у меня там было, больше не работает. Я обновил свой ответ для Java7, но если у вас есть Java8, решение очень просто:

(Я еще не проверял это)

public class DialogNew extends DialogFragment {
    private View rootView;
    private String title;
    private String message;

    // Do nothing by default
    private Consumer mSuccess = (boolean b) -> {};
    private Runnable mCancel = () -> {};

    public void setArgs(String title, String message) {
        Bundle args = new Bundle();
        args.putString("title", title);
        args.putString("message", message);
        setArguments(args);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NO_TITLE, 0);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_new_dialog, container, false);
        // use mSuccess.accept(boolean) when needed
        init();
        setListeners();
        return rootView;
    }

    public void setSuccess(Consumer success) {
        mSuccess = success;
    }

    public void setCancel(Runnable cancel) {
        mCancel = cancel;
    }
}

Тогда в основном занятии:

public class MainActivity extends BaseActivity {
        public void showNewDialog(int type, String title, String message) {
            final DialogNew dialog = new DialogNew();
            dialog.setArgs(title, message);
            dialog.setSuccess((boolean isLandscape) -> {
                //....
            });
            super.showDialogFragment(dialog);
        }
}
0
Tim Rae