Android 将数据从片段传递到DialogFragment的最佳方法

Android 将数据从片段传递到DialogFragment的最佳方法,android,Android,我试图找出在片段和DialogFragment之间传递数据的最佳方式。(双向通信) 首先,我有一个对话框片段,允许用户选择用于旅行的驾驶员/车辆。用户可以选择多个驾驶员和车辆。下面是DialogFragment类的一个片段: public class DriverVehiclePickersDialogFragment extends DialogFragment implements OnClickListener, LoaderManager.LoaderCallbacks<Curso

我试图找出在片段和DialogFragment之间传递数据的最佳方式。(双向通信)

首先,我有一个对话框片段,允许用户选择用于旅行的驾驶员/车辆。用户可以选择多个驾驶员和车辆。下面是DialogFragment类的一个片段:

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);
    }
}
这是我的驾驶课程:

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;
    }
}
下面是我的片段,它调用dialogfragment来选择驾驶员/车辆:

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());
    }
我在想,我应该把dialogfragment中的驾驶员列表和车辆列表传递给该片段吗

我还考虑将URI数组传回片段,但这不是一个好主意,因为数据库与Web服务保持同步,如果它同步并且sqlite数据库中的记录被删除,那么我将无法检索片段中的数据


我真的不知道什么是最好的解决方案,任何帮助都将不胜感激。

在不详细介绍代码的情况下,我是这样做的(通过活动将数据从片段传递到DialogFragment):

通常在Frag1中声明一个静态接口,该接口在Act中实现:

public static interface DataProxy {
   void sendData(Object ... args);
}
通过以下方法准备DFrag以接收数据:

public void recvData(Object ... data){ ... }
假设:

然后从Act开始:

@Override
public void sendData(Object ...data) {
    Fragment frag = getSupportFragmentManager().findFragmentByTag("my-dialog");
    if(frag != null && frag instanceof MyDialogFragment) {
        ((MyDialogFragment) frag).recvData(data);
    }
}

在不深入了解代码细节的情况下,以下是我的做法(通过活动将数据从片段传递到DialogFragment):

通常在Frag1中声明一个静态接口,该接口在Act中实现:

public static interface DataProxy {
   void sendData(Object ... args);
}
通过以下方法准备DFrag以接收数据:

public void recvData(Object ... data){ ... }
假设:

然后从Act开始:

@Override
public void sendData(Object ...data) {
    Fragment frag = getSupportFragmentManager().findFragmentByTag("my-dialog");
    if(frag != null && frag instanceof MyDialogFragment) {
        ((MyDialogFragment) frag).recvData(data);
    }
}

你可以选择任何你想要的方法

但请注意,在某些情况下,片段/活动可能会重新创建(如旋转设备时),因此您也需要处理它(除非您同意,否则对话框将消失)

由于您使用的是setArguments和getArguments,因此可以使用onSaveInstanceState,但同样,这取决于您在这些情况下要执行的操作


对于要传递给活动的数据,您甚至可以使用自己的侦听器。

您可以选择任何想要的方法

但请注意,在某些情况下,片段/活动可能会重新创建(如旋转设备时),因此您也需要处理它(除非您同意,否则对话框将消失)

由于您使用的是setArguments和getArguments,因此可以使用onSaveInstanceState,但同样,这取决于您在这些情况下要执行的操作


对于要传递给活动的数据,您甚至可以使用自己的侦听器。

我知道使用接口是最好的方式。我认为您的解决方案使用活动作为在片段和对话片段之间来回发送数据的方式。但是,要改写我的问题,我应该以什么格式在列表中传递片段和对话框之间的驾驶员/车辆数量?我是否应该使用泛型并使驾驶员和车辆实现parcelable?如果您通过参数发送数据,或者如果您重新创建片段(它将在某个点重新创建),则使用parcelable是值得的,并且您不想再次查询数据的来源。我理解使用Interfacees是最好的方式。我看到您的解决方案使用活动作为在片段和对话框片段之间来回发送数据的方式。但要稍微改变我的问题,我应该以什么格式在片段和对话框之间传递驾驶员/车辆列表?我应该使用泛型并使驾驶员和车辆实现parcelab吗le?如果您通过参数发送数据,或者如果您重新创建片段(它将在某个时候重新创建),并且您不想再次查询数据的源,那么使用Parcelable是值得的。