从DialogFragment向Fragment发送数据

3

我有一个包含EditText的片段,当我点击EditText时,会出现一个DatePicker对话框来选择日期。
Fragment文件

public class FirstFragment extends Fragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, container, false);
        EditText editText = (EditText) view.findViewById(R.id.visitDateFiled);

        editText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DialogFragment picker = new DatePickerFragment();
                picker.show(getFragmentManager(), "Date Picker");
            }
        });
        return view;
    }

DialogFragment

public class DatePickerFragment extends DialogFragment
        implements DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current date as the default date in the picker
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);
        // Create a new instance of DatePickerDialog and return it
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(year, month, day);

        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        String formattedDate = sdf.format(c.getTime());

    }
}

我不知道如何将数据(选定的日期)从DialogFragment传递到Fragment?


我阅读了一些主题,但对我没有帮助,我感到困惑(很抱歉再次提出这个问题)。

主题1 主题2


你可以尝试使用Observer模式,详情请见http://andhradroid.wordpress.com/2012/04/05/object-observer-pattern-in-android/。 - Heisenberg
我尝试过这个,但它没有起作用。 - Chlebta
4个回答

5

更新的代码


FragmentFile

public class FirstFragment extends Fragment implements DatePickerDialogFragmentEvents{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_first, container, false);
        EditText editText = (EditText) view.findViewById(R.id.visitDateFiled);

        editText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DialogFragment picker = new DatePickerFragment();
                picker.setDatePickerDialogFragmentEvents(FirstFragment.this); //Changed
                picker.show(getFragmentManager(), "Date Picker");
            }
        });
        return view;
    }

    //This is where you will get selected date value
    @Override
    public void onDateSelected(String date) {
        String selectedDate = date;
    } 
 }

DialogFragment

public class DatePickerFragment extends DialogFragment
        implements DatePickerDialog.OnDateSetListener {

    //Interface created for communicating this dialog fragment events to called fragment
    public interface DatePickerDialogFragmentEvents{
       void onDateSelected(String date);
    }

    DatePickerDialogFragmentEvents dpdfe

    public void setDatePickerDialogFragmentEvents(DatePickerDialogFragmentEvents dpdfe){
         this.dpdfe = dpdfe;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current date as the default date in the picker
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);
        // Create a new instance of DatePickerDialog and return it
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(year, month, day);

        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        String formattedDate = sdf.format(c.getTime());
        dpdfe.onDateSelected(formattedDate); //Changed
    }
}

所以,我在你的DialogFragment类中创建了一个名为DatePickerDialogFragmentEvents的接口,并在调用方片段中进行了实现。在调用方片段中创建DialogFragment实例时,使用DialogFragment类的setDatePickerDialogFragmentEvents方法设置片段的DatePickerDialogFragmentEvents实例。


修改后的代码行 picker.setDatePickerDialogFragmentEvents(FirstFragment.this); //Changed 无法解析。 - Chlebta
请为我检查这种方式是否有效。在setOnClickListerner中,您必须传递片段实例“this”...因为如果我传递“this”,它会采用clicklisterner并且是错误的,所以我传递了FirstFragment.this。 - Rajen Raiyarela
我已经通过这个主题的第二个响应解决了问题:https://dev59.com/K2Ml5IYBdhLWcg3wOU1g - Chlebta
它正在工作,只是不要在FirstFragment的onClickListner内部定义DialogFragment picker = new DatePickerFragment();。将其定义为DatePickerFragment picker = new DatePickerFragment();,然后setDatePickerDialogFragmentEvents无法解析的错误就会消失。 - Samrat Das

5

感谢这个主题的第二个回答,我已经解决了问题。
DatePickerFragment.java

@Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        Calendar c = Calendar.getInstance();
        c.set(year, month, day);

        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        String formattedDate = sdf.format(c.getTime());
        // in this part I stored the selected date into the intent
        Intent i = new Intent();
        i.putExtra("selectedDate",formattedDate);
        getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, i);
    }

片段文件

public static final int DATEPICKER_FRAGMENT=1; // adding this line
@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_feeding, container, false);
    EditText editText = (EditText) view.findViewById(R.id.foodDeliveryDateFiled);

    editText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            DialogFragment picker = new DatePickerFragment();
            picker.setTargetFragment(FeedingFragment.this, DATEPICKER_FRAGMENT);
            picker.show(getFragmentManager().beginTransaction(), "Date Picker");
        }
    });
    return view;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(requestCode) {
        case DATEPICKER_FRAGMENT:
            if (resultCode == Activity.RESULT_OK) {
                // here the part where I get my selected date from the saved variable in the intent and the displaying it.
                Bundle bundle=data.getExtras();
                String resultDate = bundle.getString("selectedDate","error");
                EditText editText = (EditText) getView().findViewById(R.id.foodDeliveryDateFiled);
                editText.setText(resultDate);
            }
            break;
    }

1
每个Java程序员的第一反应都是创建一个observable或callback并将其发送出去。虽然在大多数情况下这是可接受的做法,但在处理Fragments和DialogFragments时,由于重新创建、旋转、暂停时的状态损失,体验并不那么好...你可能会收到意想不到的IllegalStateExceptions异常。
我的建议有点激进,就是将你的通信模式从传递回调接口的家族移动到像Otto或GreenRobot这样的集中事件总线上。它在前台和后台都可以很好地工作,并帮助解耦使用。

-1

使用ViewModel是最佳解决方案

class ItemViewModel : ViewModel() {
        private val mutableSelectedItem = MutableLiveData<Item>()
        val selectedItem: LiveData<Item> get() = mutableSelectedItem

    fun selectItem(item: Item) {
        mutableSelectedItem.value = item
    }
}

class MainActivity : AppCompatActivity() {
    // Using the viewModels() Kotlin property delegate from the activity-ktx
    // artifact to retrieve the ViewModel in the activity scope
    private val viewModel: ItemViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.selectedItem.observe(this, Observer { item ->
            // Perform an action with the latest item data
        })
    }
}

class ListFragment : Fragment() {
    // Using the activityViewModels() Kotlin property delegate from the
    // fragment-ktx artifact to retrieve the ViewModel in the activity scope
    private val viewModel: ItemViewModel by activityViewModels()

    // Called when the item is clicked
    fun onItemClicked(item: Item) {
        // Set a new item
        viewModel.selectItem(item)
    }
}

根据Android文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接