webentwicklung-frage-antwort-db.com.de

Fragment muss eine öffentliche statische Klasse sein, um aus dem Instanzstatus ordnungsgemäß wiederhergestellt zu werden

Nach dem Update auf das neueste Support-Repository 

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'

Ich bekomme die seltsame Ausnahme.

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)

In meiner BaseActivity -Klasse habe ich ein wiederverwendbares Fragment erstellt, das in der Aktivitätsklasse verwendet werden kann und die BaseActivty erweitert.

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

Zurück zum MainActivty Ich habe das Fragment so benutzt,

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

Die DialogNew Klasse befindet sich unten,

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: Der gleiche Code funktioniert mit älterem Support-Repository. 

14

Der Fehler ist nicht besonders seltsam. Wenn Sie diesen Fehler vorher nicht erhalten haben, war das seltsam.

Android zerstört und erstellt Fragmente als Teil einer Konfigurationsänderung (z. B. Bildschirmrotation) und, falls erforderlich, eine Aufgabe (z. B. wechselt der Benutzer zu einer anderen App, der Prozess Ihrer App wird im Hintergrund beendet, danach der Benutzer) versucht, innerhalb von etwa 30 Minuten zu Ihrer App zurückzukehren). Android hat keine Möglichkeit, eine anonyme Unterklasse von DialogNew neu zu erstellen.

Erstellen Sie daher eine normale public-Java-Klasse (oder eine publicstatic-geschachtelte Klasse), die DialogNew erweitert und über Ihre Geschäftslogik verfügt. Sie ersetzt die anonyme Unterklasse von DialogNew, die Sie derzeit verwenden.

12
CommonsWare

Bearbeiten: Möglicherweise möchten Sie das nicht tun ... Siehe die Kommentare.

Das Codebeispiel sieht ähnlich aus, was ich über hier vorgeschlagen hatte, und ich entdeckte kürzlich auch, dass die Lösung, die ich dort hatte, nicht mehr funktionierte. Ich habe meine Antwort dort für Java7 aktualisiert, aber wenn Sie Java8 haben, ist die Lösung sehr einfach:

(Ich habe das noch nicht getestet)

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

Dann in der Haupttätigkeit:

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