【问题标题】:Update fragment on dialog fragment option selection在对话框片段选项选择上更新片段
【发布时间】:2012-05-17 04:36:27
【问题描述】:

我有片段,在组件上单击弹出对话框 DialogFragment。此对话框片段包含选项列表。选择从列表中的选项时,我想通知片段,以便运行字段更新过程。 我做了这样的事情

@Override
public void onClick(DialogInterface dialog, int item) {
     updateSharedPreference(item);
     Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick");
     OnCloseListDialogListener act = (OnCloseListDialogListener) getActivity();
     act.onDialogListSelection();

     dismiss();
}

但是,此 getActivity() 调用 FragmentActivity 而不是触发对话框片段的片段。 我可以杀死当前打开/运行的片段并调用一个新实例来获取更新的字段,但这是我希望避免的肮脏解决方案。

在对话片段中选择选项后,如何进行片段更新?

【问题讨论】:

  • 使用 FragmentManager 可以达到同样的效果

标签: android refresh fragment android-dialogfragment


【解决方案1】:

刚回来解决。我的问题实际上是将当前片段 getTag() 字符串作为 DialogFragment 的 show() 参数转发。如果有人对这里感兴趣是工作示例。

创建简单的监听器

public interface OnCloseListDialogListener {
    public void onDialogListSelection();
}

创建将扩展 DialogFragment 的新对话框



public class ListDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {

    private PersonaData[] mPersonaData;
    private String[] mPersonaName;
    private final String TAG;

    public static ListDialogFragment newInstance(PersonaData[] personaData, String tag) {
        ListDialogFragment dialog = new ListDialogFragment(personaData, tag);
        Bundle bundle = new Bundle();
        dialog.setArguments(bundle);
        return dialog;
    }

    private ListDialogFragment(PersonaData[] personaData, String tag) {
        this.mPersonaData = personaData.clone();
        this.TAG = tag;
    }

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setCancelable(true);
        int style = DialogFragment.STYLE_NORMAL, theme = 0;
        setStyle(style, theme);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(R.string.dialog_title);
        mPersonaName = getData();//Your own implementation here
        builder.setNegativeButton("Cancel", this);
        builder.setSingleChoiceItems(mPersonaName, -1, new SingleChoiceListener());
        return builder.create();

    }

    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
    }

    private class SingleChoiceListener implements DialogInterface.OnClickListener {
        @Override
        public void onClick(DialogInterface dialog, int item) {
            updateSharedPreference(item);
            OnCloseListDialogListener act = (OnCloseListDialogListener) getFragmentManager().findFragmentByTag(TAG);
            act.onDialogListSelection();
            dismiss();
        }
    }
}

然后在您希望从中调用此对话框的片段中执行以下操作。 DIALOG 只是我把对话框放在那里的字符串常量


SOME_CLICKABLE.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        FragmentManager manager = getFragmentManager();
        ListDialogFragment dialog = ListDialogFragment.newInstance(mPersona, getTag());
        dialog.show(manager, DIALOG);
    }
});

【讨论】:

  • getTag() 默认返回null,你需要先设置它吗?当dialogfragment在屏幕上时,它是否还能在旋转中存活?
【解决方案2】:

在大多数情况下,Fragment 有必要知道它是在某种描述的 Activity 的上下文中运行的,并且子 Fragment 可以调用父 Activity 隐式实现的接口上的方法(如您的代码 sn-p 中的演员表所示)。当您按照 Tomasz 所指出的那样让您的推荐信发挥作用时,您将获得成功。

但是,:) 为了帮助对话片段的可重用性,我建议您利用BroadcastReceivers。 BroadcastReceiver 只是广播一条消息说我做了'x'。然后,父 Activity 或实际上在任何其他顶级组件中都可以声明 我正在监听“x”。一旦在对话框组件中触发了该事件,该事件将由父 Activity 的onReceive 收集,您可以在其中运行必要的代码来更新您的字段。

就个人而言,我更喜欢这种松散耦合而不是强制转换接口方法,因为它迫使我思考每个 Fragment 的用途并使其保持模块化。

如果您想试一试,请阅读广播接收器上的开发指南部分并按照以下步骤操作;

  1. 在您的父活动中实现BroadcastReceiver。请注意,需要实现 onReceive 方法。

  2. 覆盖父 Activity 的 onResume 方法并将该 Activity 注册为具有意图操作“blah”的事件的接收者。类似的东西;

     @Override
     protected void onResume() {
     super.onResume();
     registerReceiver(this, new IntentFilter("blah"));
    }
    
  3. 覆盖父 Activity 的 onPause 方法,将 Activity 取消注册为接收器,以避免“泄露的接收器”(你会发现)。

    @Override
    protected void onPause() {
     super.onPause();
     unregisterReceiver(deleteSpotReceiver);
    }
    
  4. 在您的 DialogFragment onClick 中触发您的父活动正在“侦听”的事件。

    @Override
    public void onClick(DialogInterface dialog, int item) {
        updateSharedPreference(item);
        Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick");
        final Intent intent = new Intent();
        intent.setAction("blah");
        getActivity().sendBroadcast(intent);
        dismiss();
    }
    

父活动将收集消息,您可以继续处理。如果您决定采用这种方法,请告诉我。

【讨论】:

  • 优秀的迷你指南!正是我想要的。
  • 很棒的指南!不过,我仍然不确定是否将回调发送到活动。在我的情况下,我有一个包含几个“主要”片段的导航抽屉。让活动传递有关被单击的对话框的信息似乎有点破损。在创建对话框时注册监听器不是更合适吗?
  • 嗨 Sam,只要底层的 Fragments 不知道它们在视图层次结构中的位置,那么该方法就保持可靠。如果 Fragment A 作为具体类型直接与 Fragment B/Activity B 通信,那么它们是不适当的耦合。回调替代方案在片段 A 不“知道”谁感兴趣的情况下很受欢迎,只是有人感兴趣 - 这可以通过类似侦听器的接口回调或通过 EventBus 方法来完成。就 Android 而言,只要你从不写 ((MySoooperActivityOrFragment) getActivity()).invokeMySooperMethod() 我就可以了 ;)
【解决方案3】:

就像你在上面做的那样,在你的活动中添加这样的东西:

public void onDialogListSelection() {
    AnotherFragment anotherFragment = (AnotherFragment) getSupportFragmentManager()
            .findFragmentById(R.id.anotherFragment);
    anotherFragment.customMethodToNotifyListHasBeenSelected();
}

当然,如果您不使用支持库,请调用 getFragmentManager 而不是 getSupportFragmentManager

【讨论】:

  • 不起作用,归结为该片段是通过从另一个片段单击按钮调用/调用的子片段,因此我无法获取 ID,也尝试使用标签但失败: (
  • @peter_budo:如果您在代码中在运行时创建弹出片段,那么您可以保留对它的引用以供以后使用。
  • 对不起,你能详细说明一下吗?谢谢
  • @peter_budo:当然,如果您提供当前代码,我可以提出一些建议。但它只是将创建的片段存储在活动的成员字段中。或者,即使您在运行时创建片段,您仍然可以将其与标签相关联。提示:使用DialogTransaction.add(int containerViewId, Fragment fragment, String tag) 而不是DialogTransaction.add(int containerViewId, Fragment fragment)(DailogFragment 的show 似乎只有带有标签参数的版本:DailogFragments.show(FragmentTransaction transaction, String tag)
  • 好的,这里是ProfileStatsFragment,我在第 126 行调用对话框,然后这里是 ProfilePersonaListDialog 第 95-99 行,片段通知应该发生。 (目前代码有点乱,我正在帮助项目)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多