如何通过配置更改保留对象引用?

时间:2011-11-17 22:33:33

标签: android dialog

我创建了可重复使用的文本查询对话框片段。但它不处理配置。变化。片段重新创建后,mClickListener为null(如预期的那样)。问题是 - 我如何保留回调? (我是java的新手,可能不知道常见的java模式/解决方案)

public class TextQueryDialogFragment extends DialogFragment {
private OnDialogListener mClickListener;
private EditText mTextWidget;

public void setClickListener(OnDialogListener listener) {
    mClickListener = listener;
}

public String getQueryText() {
    return mTextWidget.getText().toString();
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater factory = LayoutInflater.from(getActivity());
    final View queryView = factory.inflate(R.layout.query_dialog_text, null);
    mTextWidget = (EditText) queryView.findViewById(R.id.query_dialog_text);

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
    .setView(queryView)
    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            if(null != mClickListener)
                mClickListener.OnPositiveClick();
            dialog.dismiss();
        }
    })
    .setNegativeButton(android.R.string.cancel, 
                                           new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            if(null != mClickListener)
                mClickListener.OnNegativeClick();
            dialog.cancel();
        }
    });

    return builder.create();
}
}

用法:

TextQueryDialogFragment dialog = new TextQueryDialogFragment();
dialog.setQueryText(mBookmarkTitle);
dialog.setClickListener(new OnDialogListener() {
        @Override
        public void OnPositiveClick() {
            String title = dialog.getQueryText();
            //do work here
        }

        @Override
        public void OnNegativeClick() {}
    });
dialog.show(getFragmentManager(), "MYTAG");

Serializable不起作用,因此onSaveInstanceState不是我需要的。 Parcelable可能会(使用aidl和IBinder)但这对于这么简单的任务来说太过分了。

到目前为止,我发现了两种或多或少不太合适的解决方案:

  • 在应用程序中存储回调并通过id / tag taken from here
  • 检索它们
  • 在创建父片段时更新回调:

    TextQueryDialogFragment dialog =(TextQueryDialogFragment)              。getFragmentManager()findFragmentByTag(RENAME_TAG); if(null!= dialog){ dialog.setClickListener(getListener()); }

有没有更好的解决方案,或者那两个可以吗?

3 个答案:

答案 0 :(得分:2)

解决方案很简单,与onRetainConfigurationInstance或此处提到的其他技术无关。只需在重新创建父片段时在TextQueryDialogFragment中搜索FragmentManager实例,并在实例仍然存在的情况下再次设置侦听器。

将以下代码添加到父onCreateView方法:

TextQueryDialogFragment retFragment = 
(TextQueryDialogFragment)getFragmentManager().findFragmentByTag("MYTAG");

if(retFragment != null)
{
    retFragment.setClickListener(new OnDialogListener() {
        @Override
        public void OnPositiveClick() {
            String title = dialog.getQueryText();
            //do work here
        }

        @Override
        public void OnNegativeClick() {}
    }
);
}

在这种情况下,我宁愿通过您的片段类实现onClickListener,以便您可以这样重写它:

TextQueryDialogFragment retFragment = 
(TextQueryDialogFragment )getFragmentManager().findFragmentByTag("MYTAG");

if(retFragment != null)
{
    retFragment.setClickListener(this);
}

答案 1 :(得分:0)

我认为您正在寻找onRetainConfigurationInstance,您可以返回任何您想要的对象。

public Object onRetainNonConfigurationInstance() { ... }

然后你可以在onCreate()中找到它:

if (getLastNonConfigurationInstance() != null) {
  instance = (Type) getLastNonConfigurationInstance();
}

但是,我不确定为什么你需要保留OnClickListener

答案 2 :(得分:0)

我遇到了类似的问题,而vitakot的答案就是解决方案!但我的情况稍微复杂一点:我有一个片段'MyAttributeFragment',它使用DialogFragment进行文本输入。此MyAttributeFragment在同一个Activity中使用了多次,因此DialogFragment的静态标记(如“MYTAG”)不是唯一的。我通过获取MyAttributeFragment的ID来识别拥有的片段来解决这个问题。

//Create DialogFragment with the unique ID of the owning fragment 
newFragment.show(getFragmentManager(), String.valueOf(this.getId()));