我使用DialogFragments的一些事情:从列表中选择项目,输入文本。

将值(即字符串或列表中的项)返回给调用活动/片段的最佳方法是什么?

目前,我正在使调用活动实现驳回监听器,并给予DialogFragment对活动的引用。然后Dialog在activity中调用ondismiss方法,activity从DialogFragment对象中抓取结果。非常混乱,它不能在配置更改(方向更改),因为DialogFragment失去了对活动的引用。

谢谢你的帮助。


当前回答

在我的例子中,我需要将参数传递给一个targetFragment。但我发现异常"碎片已激活"所以我在我的DialogFragment中声明了一个接口,这是parentFragment实现的。当parentFragment启动一个DialogFragment时,它将自己设置为TargetFragment。然后在DialogFragment中调用

 ((Interface)getTargetFragment()).onSomething(selectedListPosition);

其他回答

在我的例子中,我需要将参数传递给一个targetFragment。但我发现异常"碎片已激活"所以我在我的DialogFragment中声明了一个接口,这是parentFragment实现的。当parentFragment启动一个DialogFragment时,它将自己设置为TargetFragment。然后在DialogFragment中调用

 ((Interface)getTargetFragment()).onSomething(selectedListPosition);

在Kotlin

    // My DialogFragment
class FiltroDialogFragment : DialogFragment(), View.OnClickListener {
    
    var listener: InterfaceCommunicator? = null

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        listener = context as InterfaceCommunicator
    }

    interface InterfaceCommunicator {
        fun sendRequest(value: String)
    }   

    override fun onClick(v: View) {
        when (v.id) {
            R.id.buttonOk -> {    
        //You can change value             
                listener?.sendRequest('send data')
                dismiss()
            }
            
        }
    }
}

//我的活动

class MyActivity: AppCompatActivity(),FiltroDialogFragment.InterfaceCommunicator {

    override fun sendRequest(value: String) {
    // :)
    Toast.makeText(this, value, Toast.LENGTH_LONG).show()
    }
}
 

我希望它服务,如果你可以改进,请编辑它。 我的英语不太好

或者像下面这样共享ViewModel:

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}

https://developer.android.com/topic/libraries/architecture/viewmodel#sharing_data_between_fragments

使用myDialogFragment。setTargetFragment(this, MY_REQUEST_CODE)从你显示对话框的地方,然后当你的对话框完成时,从它可以调用getTargetFragment().onActivityResult(getTargetRequestCode(),…),并在包含的片段中实现onActivityResult()。

这似乎是对onActivityResult()的滥用,特别是因为它根本不涉及活动。但我看到官方谷歌的人推荐它,甚至可能在api演示中。我认为这是g/setTargetFragment()被添加的原因。

正如你在这里看到的,有一个非常简单的方法来做到这一点。

在你的DialogFragment中添加一个接口监听器:

public interface EditNameDialogListener {
    void onFinishEditDialog(String inputText);
}

然后,添加对该监听器的引用:

private EditNameDialogListener listener;

这将被用来“激活”监听器方法,也用来检查父Activity/Fragment是否实现了这个接口(见下文)。

在“调用”DialogFragment的Activity/FragmentActivity/Fragment中简单地实现了这个接口。

在你的DialogFragment中,你需要在你想要解散DialogFragment并返回结果的地方添加以下内容:

listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();

mEditText.getText(). tostring()将被传递回调用Activity。

注意,如果您想返回其他内容,只需更改侦听器所接受的参数。

最后,你应该检查接口是否由父活动/片段实际实现:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    // Verify that the host activity implements the callback interface
    try {
        // Instantiate the EditNameDialogListener so we can send events to the host
        listener = (EditNameDialogListener) context;
    } catch (ClassCastException e) {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(context.toString()
                + " must implement EditNameDialogListener");
    }
}

这种技术非常灵活,即使你还不想结束对话框,也可以回调结果。