Best Way To Pass Data From Fragment To DialogFragment
我正在尝试找出在 Fragment 和 DialogFragment 之间传递数据的最佳方式。 (2路通讯)
首先我有一个对话框片段,允许用户选择用于旅行的司机/车辆。用户可以选择多个司机和车辆。这是 DialogFragment 类的片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | public class DriverVehiclePickersDialogFragment extends DialogFragment implements OnClickListener, LoaderManager.LoaderCallbacks<Cursor> { private static final int DRIVERS_LOADER = 0; private static final int VEHICLES_LOADER = 1; // Parent view for all rows and the add button. private LinearLayout mContainerView; // These are the Contacts rows that we will retrieve. static final String[] DRIVERS_SUMMARY_PROJECTION = new String[] { BaseColumns._ID, ConsoleContract.Drivers.DRIVER_NUMBER, ConsoleContract.Drivers.DRIVER_NAME }; static final String[] VEHICLES_SUMMARY_PROJECTION = new String[] { BaseColumns._ID, ConsoleContract.Vehicles.VEHICLE_NUMBER, ConsoleContract.Vehicles.VEHICLE_VIN }; public interface DriverVehicleDialogListener { public void onDialogPositiveClick(????????); } @Override public void onClick(View v) { if (v.equals(mSet)) { if (checkDriversVehiclesValidity()) { mListener.onDialogPositiveClick(???????????); this.dismiss(); } } else if (v.equals(mCancel)) { this.dismiss(); } else if (v.equals(mAddNew)) { inflateEditRow(); } else if (v instanceof ImageButton) { mContainerView.removeView((View) v.getParent()); } } // Helper for inflating a row private void inflateEditRow() { Bundle args = getArguments(); DialogType dialogType = (DialogType) args.getSerializable(ARG_DIALOG_TYPE); final View rowView = getActivity().getLayoutInflater().inflate(R.layout.driver_vehicle_row, null); CustomAutoCompleteTextView driversField, vehiclesField; if ((dialogType == DialogType.DRIVER_SPINNER) || (dialogType == DialogType.DRIVER_VEHICLE_SPINNER)) { driversField = (CustomAutoCompleteTextView) rowView.findViewById(R.id.drivers_field); driversField.setThreshold(0); driversField.setAdapter(mDriversAdapter); driversField.setVisibility(View.VISIBLE); } if ((dialogType == DialogType.VEHICLE_SPINNER) || (dialogType == DialogType.DRIVER_VEHICLE_SPINNER)) { vehiclesField = (CustomAutoCompleteTextView) rowView.findViewById(R.id.vehicles_field); vehiclesField.setThreshold(0); vehiclesField.setAdapter(mVehiclesAdapter); vehiclesField.setVisibility(View.VISIBLE); } ImageButton mDelete = (ImageButton) rowView.findViewById(R.id.buttonDelete); mDelete.setOnClickListener(this); // Inflate at the end of all rows but before the"Add new" button mContainerView.addView(rowView, mContainerView.getChildCount() - 1); } } |
这是我的车辆类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public static final class Vehicles implements VehicleColumns, BaseColumns { public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_VEHICLES).build(); public static final String CONTENT_TYPE ="vnd.android.cursor.dir/com.test.console.vehicles"; public static final String CONTENT_ITEM_TYPE ="vnd.android.cursor.item/vnd.console.vehicles"; private int vehicle_id, vehicle_number; private String vehicle_vin; public Vehicles() { } public Vehicles(int vehicleID, int vehicleNumber, String vehicleVin) { setVehicleID(vehicleID); setVehicleNumber(vehicleNumber); setVehicleVin(vehicleVin); } public int getVehicleID() { return vehicle_id; } public void setVehicleID(int mVehicleID) { this.vehicle_id = mVehicleID; } public int getVehicleNumber() { return vehicle_number; } public void setVehicleNumber(int mVehicleNumber) { this.vehicle_number = mVehicleNumber; } public String getVehicleVin() { return vehicle_vin; } public void setVehicleVin(String mVehicleVin) { this.vehicle_vin = mVehicleVin; } public static Uri buildVehicleUri(String vehicleID) { return CONTENT_URI.buildUpon().appendPath(vehicleID).build(); } } |
这是我的司机课程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public static final class Drivers implements DriverColumns, BaseColumns { public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(PATH_DRIVERS).build(); public static final String CONTENT_TYPE ="vnd.android.cursor.dir/com.test.console.drivers"; public static final String CONTENT_ITEM_TYPE ="vnd.android.cursor.item/vnd.console.drivers"; private int driver_id, driver_number; private String driver_name; public Drivers() { } public Drivers(int driverID, int driverNumber, String driverName) { this.setDriverID(driverID); this.setDriverNumber(driverNumber); this.setDriverName(driverName); } public static Uri buildDriverUri(String driverID) { return CONTENT_URI.buildUpon().appendPath(driverID).build(); } public int getDriverID() { return driver_id; } public void setDriverID(int driver_id) { this.driver_id = driver_id; } public int getDriverNumber() { return driver_number; } public void setDriverNumber(int driver_number) { this.driver_number = driver_number; } public String getDriverName() { return driver_name; } public void setDriverName(String driver_name) { this.driver_name = driver_name; } } |
这是我的片段,它调用对话片段来选择驾驶员/车辆:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class CrewTripFragment extends Fragment implements DateTimeDialogListener, CrewCountDialogListener, DriverVehicleDialogListener, OnItemSelectedListener { @Override public void onDialogPositiveClick(????) { //I need a list of drivers+vehicles selected so i can use it in the fragment. //an example would be: //DriverID: 10 DriverName: John DriverNumber 30 - VehicleID 10 VehicleNumber: 24 VehicleVin: 34848 } protected void showDriverVehicleDialog() { // Creating a bundle object Bundle bundleSettings = new Bundle(); bundleSettings.putInt(DriverVehiclePickersDialogFragment.ARG_TITLE_RESOURCE, R.string.crew_driver_vehicle_title); bundleSettings.putSerializable(DriverVehiclePickersDialogFragment.ARG_DIALOG_TYPE, DriverVehiclePickersDialogFragment.DialogType.DRIVER_VEHICLE_SPINNER); if (mDrivers != null) { bundleSettings.putLongArray(DriverVehiclePickersDialogFragment.ARG_SET_DRIVER, mDrivers); } if (mVehicles != null) { bundleSettings.putLongArray(DriverVehiclePickersDialogFragment.ARG_SET_VEHICLE, mVehicles); } DriverVehiclePickersDialogFragment dialogDriverVehiclePicker = DriverVehiclePickersDialogFragment.newInstance(this, bundleSettings); dialogDriverVehiclePicker.show(getFragmentManager(), getTag()); } |
我在考虑是否应该将对话片段中的驾驶员列表和车辆列表传递回片段?
我也在考虑将一组 URI 传回片段,但这不是一个好主意,因为数据库与 web 服务保持同步,如果它同步并且 sqlite 数据库中的记录被删除,那么我无法检索片段内的数据。
我真的不确定什么是最好的解决方案,任何帮助将不胜感激。
你可以选择任何你想要的方法。
请注意,在某些情况下,片段/活动可能会重新创建(例如当您旋转设备时),因此您也需要处理它(除非您对此感到满意,否则对话框将消失。
由于您使用 setArguments 和 getArguments,您可以使用 onSaveInstanceState ,但同样,这完全取决于您想在这些情况下做什么。
对于要传递给活动的数据,您甚至可以使用自己的侦听器。
如果不仔细研究您的代码,我就是这样做的(通过 Activity 将数据从 Fragment 传递到 DialogFragment ):
像往常一样在 Frag1 中声明一个在 Act:
中实现的静态接口
1 2 3 | public static interface DataProxy { void sendData(Object ... args); } |
通过某种方法准备 DFrag 以接收数据:
1 | public void recvData(Object ... data){ ... } |
假设 DFrag 使用标签显示:
1 2 | DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel); newFragment.show(getSupportFragmentManager().beginTransaction(),"my-dialog"); |
然后从 Act:
1 2 3 4 5 6 7 | @Override public void sendData(Object ...data) { Fragment frag = getSupportFragmentManager().findFragmentByTag("my-dialog"); if(frag != null && frag instanceof MyDialogFragment) { ((MyDialogFragment) frag).recvData(data); } } |