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

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

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

谢谢你的帮助。


当前回答

不同的方法,允许一个片段与它的活动通信:

1)在片段中定义一个公共接口,并为其创建一个变量

public OnFragmentInteractionListener mCallback;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(int id);
}

2)将活动转换为片段中的mCallback变量

try {
    mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
    Log.d(TAG, e.getMessage());
}

3)在你的活动中实现监听器

public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener  {
     //your code here
}

4)在活动中覆盖OnFragmentInteraction

@Override
public void onFragmentInteraction(int id) {
    Log.d(TAG, "received from fragment: " + id);
}

更多信息:https://developer.android.com/training/basics/fragments/communicating.html

其他回答

在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()
    }
}
 

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

不同的方法,允许一个片段与它的活动通信:

1)在片段中定义一个公共接口,并为其创建一个变量

public OnFragmentInteractionListener mCallback;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(int id);
}

2)将活动转换为片段中的mCallback变量

try {
    mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
    Log.d(TAG, e.getMessage());
}

3)在你的活动中实现监听器

public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener  {
     //your code here
}

4)在活动中覆盖OnFragmentInteraction

@Override
public void onFragmentInteraction(int id) {
    Log.d(TAG, "received from fragment: " + id);
}

更多信息:https://developer.android.com/training/basics/fragments/communicating.html

或者像下面这样共享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

我很惊讶地看到,没有人建议使用本地广播进行DialogFragment到Activity的通信!我发现它比其他建议更简单、更清晰。本质上,您为您的Activity注册侦听广播,并从您的DialogFragment实例发送本地广播。简单。有关如何设置它的一步一步的指南,请参见这里。

对于还在阅读这篇文章的人:setTargetFragment()已被弃用。现在建议像这样使用FragmentResultListener API:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setFragmentResultListener("requestKey") { key, bundle ->
        val result = bundle.getString("resultKey")
        // Do something with the result...
    }

    ...

    // Somewhere show your dialog
    MyDialogFragment.newInstance().show(parentFragmentManager, "tag")
}

然后在你的MyDialogFragment中设置结果:

button.setOnClickListener{
    val result = "some string"
    setFragmentResult("requestKey", bundleOf("resultKey" to result))
    dismiss()
}