Фрагмент должен быть общедоступным статическим классом, который должен быть правильно воссоздан из состояния экземпляра
После обновления до последнего репозитория поддержки
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 я создал повторно используемый фрагмент, который можно использовать в классе активности, который расширяет 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: тот же код работает со старым репозиторием поддержки.
Ответы
Ответ 1
Ошибка не особенно странная. Если вы раньше не получали эту ошибку, это было странно.
Android уничтожает и воссоздает фрагменты как часть изменения конфигурации (например, поворот экрана) и как часть перестройки задачи, если это необходимо (например, пользователь переключается на другое приложение, ваш процесс приложения завершается, когда он находится в фоновом режиме, то пользователь пытается вернуться в ваше приложение, все в течение 30 минут или около того). Android не имеет возможности воссоздать анонимный подкласс DialogNew
.
Итак, создайте обычный public
класс Java (или public
static
вложенный класс), который расширяет DialogNew
и имеет вашу бизнес-логику, заменив анонимный подкласс DialogNew
, который вы используете в настоящее время.
Ответ 2
Изменить: Вы, вероятно, не хотите этого делать... См. комментарии.
Пример кода похож на то, что я предложил в здесь, а также недавно обнаружил, что решение, которое у меня там было, больше не работает. Я обновил свой ответ там для 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);
}
}