public class ExampleDialogFragment extends DialogFragment { private Listener listener; public interface Listener { void onMessageEntered(String msg); } @Override public void onAttach (Context context) { super.onAttach(context); if(context instanceOf Listener) { listener = (Listener) context; } else { listener = (Listener) getParentFragment(); } } }
public class ExampleDialogFragment extends DialogFragment { private Listener listener; public interface Listener { void onMessageEntered(String msg); } public static DialogFragment newInstance(Listener listener) { ExampleDialogFragment dialogFragment = new ExampleDialogFragment(); dialogFragment.listener = listener; return dialogFragment; } }
public class ExampleActivity extends AppCompatActivity { void showDialog() { DialogFragment dialogFragment = ExampleDialogFragment .newInstance(new DialogFragment.Listener() { @Override void onMessageEntered(String msg) { // TODO } }); dialogFragment.show(getFragmentManager(), "dialog"); } }
Bundle
and will be destroyed -> activations will be deleted -> a new instance of activations will be created -> the dialog will be recreated based on the state saved in the Bundle
. As a result, we will lose the link to the listener in the dialogue, since it was clearly not saved and restored. setListener()
course, we can manually call setListener()
in one of the callbacks of the activation life cycle, but there is another option. Since we cannot save an anonymous class in the Bundle
, as well as instances of regular classes, we need to meet the following conditions:Serializable
or Parcelable
setArguments(Bundle args)
onSaveInstanceState(Bundle outState)
method onSaveInstanceState(Bundle outState)
Dialog onCreateDialog(Bundle savedInstanceState)
method Dialog onCreateDialog(Bundle savedInstanceState)
Activity
or Fragment
. Such components are not intended to be saved in the Bundle
, so we need to find a different approach to the solution. Let's try not to transmit the listener himself, but the “ Provider” who is able to find him. In this case, no one will hurt us to make it serializable and save it in the Bundle
.onSaveInstanceState(Bundle outState)
method and restore the dependency from the arguments by calling the Dialog onCreateDialog(Bundle savedInstanceState)
method. public class ExampleDialogFragment extends DialogFragment { private static final String LISTENER_PROVIDER = "listener_provider"; private Listener listener; public interface ListenerProvider extends Serializable { Listener from(DialogFragment dialogFragment); } public interface Listener { void onMessageEntered(String msg); } public static DialogFragment newInstance(ListenerProvider provider) { ExampleDialogFragment dialogFragment = new ExampleDialogFragment(); Bundle args = new Bundle(); args.putSerializable(LISTENER_PROVIDER, provider); dialogFragment.setArguments(args); return dialogFragment; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle args = getArguments(); if(args == null || !args.containsKey(LISTENER_PROVIDER)) { throw new IllegalStateException("Listener provider is missing"); } ListenerProvider listenerProvider = (ListenerProvider) args.getSerializable(LISTENER_PROVIDER); Listener listener = listenerProvider.from(this); ... } }
public class ExampleActivity extends AppCompatActivity implements ExampleDialogFragment.Listener { @Override public void onMessageEntered(String msg) { // TODO } void showDialog() { DialogFragment dialogFragment = ExampleDialogFragment .newInstance(new ListenerProvider()); dialogFragment.show(getFragmentManager(), "dialog"); } private static class ListenerProvider implements ExampleDialogFragment.ListenerProvider { private static final long serialVersionUID = -5986444973089471288L; @Override public ExampleDialogFragment.Listener from(DialogFragment dialogFragment) { return (ExampleDialogFragment.Listener) dialogFragment.getActivity(); } } }
public class ExampleFragment extends Fragment implements ExampleDialogFragment.Listener { @Override public void onMessageEntered(String msg) { // TODO } void showDialog() { DialogFragment dialogFragment = ExampleDialogFragment.newInstance(new ListenerProvider()); dialogFragment.show(getFragmentManager(), "dialog"); } private static class ListenerProvider implements ExampleDialogFragment.ListenerProvider { private static final long serialVersionUID = -5986444973089471288L; @Override public ExampleDialogFragment.Listener from(DialogFragment dialogFragment) { return (ExampleDialogFragment.Listener) dialogFragment.getParentFragment(); } } }
Activity
directly, then no one bothers to just throw the event and then catch it in the right place and process it (the dialog code will not even need to be changed): public class ExampleFragment extends Fragment { void onMessageEvent(Message message) { // TODO } void showDialog() { DialogFragment dialogFragment = ExampleDialogFragment.newInstance(new ListenerProvider()); dialogFragment.show(getFragmentManager(), "dialog"); } private static class Message { public final String content; private Message(String content) { this.content = content; } } private static class ListenerProvider implements ExampleDialogFragment.ListenerProvider { private static final long serialVersionUID = -5986444973089471288L; @Override public ExampleDialogFragment.Listener from(DialogFragment dialogFragment) { return new ExampleDialogFragment.Listener() { @Override public void onMessageEntered(String msg) { EventBus.getDefault().post(new Message(msg)); } }; } } }
Activity <-> Fragment
or Fragment <-> Fragment
within the framework of one activit. The general principle remains the same as was described above: through the interface (for example, Listener) and the “detective”, communication between the components is organized. In this article we will consider one-way interaction. public interface Presenter { ... } public class ExampleFragment extends Fragment { private Presenter presenter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter = App.get().getExampleFragmentComponent().getPresenter(); } }
public class ExampleFragment extends Fragment { private static final String DI_PROVIDER = "di_provider"; private Presenter presenter; public interface DependencyProvider implements Serializable { Presenter getPresenterOf(Fragment fragment); } public static Fragment newInstance(DependencyProvider dependencyProvider) { Fragment fragment = new ExampleFragment(); Bundle args = new Bundle(); args.putSerializable(DI_PROVIDER, dependencyProvider); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); if(args == null || !args.containsKey(DI_PROVIDER)) { throw new IllegalStateException("DI provider is missing"); } DependencyProvider diProvider = (DependencyProvider) args.getSerializable(DI_PROVIDER); presenter = diProvider.getPresenterOf(this); } } public class ExampleActivity extends AppCompatActivity { void showFragment() { FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment fragment = ExampleFragment .newInstance(new DiProvider()); ft.add(R.id.container, fragment); ft.commit(); } private static class DiProvider implements ExampleFragment.DependencyProvider { private static final long serialVersionUID = -5986444973089471288L; @Override public Presenter get(Fragment fragment) { return App.get().getExampleFragmentComponent().getPresenter(); } } }
Activity
.Source: https://habr.com/ru/post/342038/
All Articles