DialogFragment getView возвращает значение null при onDismiss

У меня есть собственный диалог, полученный из DialogFragment.

Когда пользователь нажимает кнопку «ОК», мне нужно сохранить информацию, которая находится на экране.

Поэтому я отклонил вызовы PositiveButton и реализовал метод onDismiss для сохранения данных.

В методе onDismiss мне нужно получить данные из editView, который находится в диалоговом окне. Я использую getView().findViewByID для получения editView, но метод GetView() возвращает null.

Вот мой код:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    LayoutInflater inflater = getActivity().getLayoutInflater();

    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().dismiss();
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().cancel();
               }
           });      
    return builder.create();
}

@override
public void onDismiss(){
    EditView view = (EditView)getView().findViewByID(R.id.edit);
}

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

Как правильно получить вид с экрана в onDismiss?

Ps: место, где я работаю, не позволяет мне публиковать мой код, поэтому я взял код из Google и изменил его, чтобы он был как можно ближе к моему коду.


person jonathanrz    schedule 22.05.2013    source источник


Ответы (2)


Старый но золотой. Это позволяет лучше контролировать весь фрагмент (например, при реализации seekBar или использовании ButterKnife). Достаточно сказано:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    LayoutInflater inflater = getActivity().getLayoutInflater();

    View view = inflater.inflate(R.layout.dialog_signin, null);
    // do your stuff with views here

    builder.setView(view)
       .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
           @Override
           public void onClick(DialogInterface dialog, int id) {
               LoginDialogFragment.this.getDialog().dismiss();
           }
       })
       .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               LoginDialogFragment.this.getDialog().cancel();
           }
       });      
    return builder.create();
}

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

Да, это тот. Тем не менее, это выглядит правильно, особенно при реализации таких вещей, как seekBar, и при использовании таких библиотек, как ButterKnife.

person Darek Deoniziak    schedule 24.10.2015
comment
Через два года я тоже так делаю :) - person jonathanrz; 24.10.2015
comment
Формулировка этого ответа очень двусмысленна. Вместо того, чтобы сказать «Да, это он». Хотя это выглядит правильно, почему бы не сказать, что это правильный способ сделать это? Если предположить, что это то, что вы говорите, я все еще не совсем уверен. - person joe_deniable; 29.06.2016
comment
Мало сказано, на мой взгляд. Я также изо всех сил пытаюсь понять, что предлагает этот ответ - как с точки зрения кода, так и с точки зрения объяснения. - person ban-geoengineering; 23.01.2017
comment
Одна вещь, которую, возможно, стоит добавить, заключается в том, что, возможно, стоит установить mView в null в onDestroy(), поскольку в противном случае вы могли бы получить утечку памяти (??). - person ban-geoengineering; 23.01.2017
comment
@ban-geoengineering Да, но только если вы используете глобальную переменную. Пример выше имеет локальную переменную View. - person Darek Deoniziak; 24.01.2017

Способ входа в систему DialogFragment заключался в использовании метода обратного вызова для родительской активности фрагмента, например:

builder.setPositiveButton("Login", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                EditText username = (EditText) getDialog().findViewById(R.id.username);
                EditText password = (EditText) getDialog().findViewById(R.id.password);                 

                un = username.getText().toString();
                pw = password.getText().toString();

                    if (un.equals("") || pw.equals("")) {
                        Toast.makeText(getActivity(), "Username or Password field was empty", Toast.LENGTH_SHORT).show();
                        //Don't login & do something (I made a recursive callback to the fragment that created the dialog)
                    }
                    else if (!un.equals("username") || !pw.equals("password")) {
                        Toast.makeText(getActivity(), "Username or Password was incorrect", Toast.LENGTH_SHORT).show();
                        //Don't login & do something (I made a recursive callback to the fragment that created the dialog)
                    }
                    else if (un.equals("username") && pw.equals("password")) {
                        Toast.makeText(getActivity(), "You have logged in successfully", Toast.LENGTH_SHORT).show();
                        mLogin.Login();
                    }

Затем метод обратного вызова Login() создаст следующий необходимый фрагмент.

Фрагмент, который создаст ваш диалог входа в систему, будет иметь следующий код в своем методе обратного вызова:

LoginDialog login = new LoginDialog();
login.show(getFragmentManager(), "LOGIN");
person TronicZomB    schedule 22.05.2013
comment
Спасибо за Ваш ответ. Безопасно ли передавать возврат getDialog() моему классу Dialog? - person jonathanrz; 23.05.2013
comment
Я не уверен, что вы имеете в виду под этим? Вам не нужно бросать ...? - person TronicZomB; 23.05.2013
comment
Метод getDialog возвращает объект типа Dialog. Мой диалог расширяется от DialogFragment. Могу ли я сделать следующее: MyDialog dlg = (MyDialog)getDialog();? - person jonathanrz; 23.05.2013
comment
О, создать диалог изначально в родительской активности фрагмента? - person TronicZomB; 23.05.2013
comment
Я обновил свой ответ, чтобы показать, как это сделать. Теперь там, где написано LoginDialog, это имя файла класса java, который содержит ваш DialogFragment. - person TronicZomB; 23.05.2013