我有一个DialogFragment
我正在努力显示两个微调器,并排显示一个驱动程序列表,另一个显示车辆列表。
填充这些微调器的数据是从 sqlite 数据库中检索的。我正在尝试使用 aLoaderManager
来保持微调器的更新或与数据库表(驱动程序和车辆)同步。
当我在数据库的驱动程序表或车辆表中添加/删除/编辑记录时,微调器不会更新,驱动程序或车辆在微调器中保持不变。
我不确定我错过了什么,因为我认为LoaderManager
应该自动更新列表或与数据库表同步,对吗?
我创建了一个名为的按钮addDriverVehicle()
,它应该允许用户在将来添加另一个驱动程序/车辆,但现在我用它作为测试来删除一个驱动程序来模拟数据库表的变化,这样我就可以看看是否微调器会自动更新,但没有发生。记录正在被删除,但微调器继续显示它。
public class DriverVehiclePickersDialogFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<Cursor>, OnItemSelectedListener {
public static final String ARG_LISTENER_TYPE = "listenerType";
public static final String ARG_DIALOG_TYPE = "dialogType";
public static final String ARG_TITLE_RESOURCE = "titleResource";
public static final String ARG_SET_DRIVER = "setDriver";
public static final String ARG_SET_VEHICLE = "setVehicle";
private static final int DRIVERS_LOADER = 0;
private static final int VEHICLES_LOADER = 1;
private DriverVehicleDialogListener mListener;
// These are the Adapter being used to display the driver's and vehicle's data.
SimpleCursorAdapter mDriversAdapter, mVehiclesAdapter;
// Define Dialog view
private View mView;
// Store Driver and Vehicle Selected
private long[] mDrivers, mVehicles;
// Spinners Containing Driver and Vehicle List
private Spinner driversSpinner;
private Spinner vehiclesSpinner;
private static enum ListenerType {
ACTIVITY, FRAGMENT
}
public static enum DialogType {
DRIVER_SPINNER, VEHICLE_SPINNER, DRIVER_VEHICLE_SPINNER
}
public interface DriverVehicleDialogListener {
public void onDialogPositiveClick(long[] mDrivers, long[] mVehicles);
}
public DriverVehiclePickersDialogFragment() {
// Empty Constructor
Log.d("default", "default constructor ran");
}
public static DriverVehiclePickersDialogFragment newInstance(DriverVehicleDialogListener listener, Bundle dialogSettings) {
final DriverVehiclePickersDialogFragment instance;
if (listener instanceof Activity) {
instance = createInstance(ListenerType.ACTIVITY, dialogSettings);
} else if (listener instanceof Fragment) {
instance = createInstance(ListenerType.FRAGMENT, dialogSettings);
instance.setTargetFragment((Fragment) listener, 0);
} else {
throw new IllegalArgumentException(listener.getClass() + " must be either an Activity or a Fragment");
}
return instance;
}
private static DriverVehiclePickersDialogFragment createInstance(ListenerType listenerType, Bundle dialogSettings) {
DriverVehiclePickersDialogFragment fragment = new DriverVehiclePickersDialogFragment();
if (!dialogSettings.containsKey(ARG_LISTENER_TYPE)) {
dialogSettings.putSerializable(ARG_LISTENER_TYPE, listenerType);
}
if (!dialogSettings.containsKey(ARG_DIALOG_TYPE)) {
dialogSettings.putSerializable(ARG_DIALOG_TYPE, DialogType.DRIVER_VEHICLE_SPINNER);
}
if (!dialogSettings.containsKey(ARG_TITLE_RESOURCE)) {
dialogSettings.putInt(ARG_TITLE_RESOURCE, 0);
}
fragment.setArguments(dialogSettings);
return fragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Find out how to get the DialogListener instance to send the callback events to
Bundle args = getArguments();
ListenerType listenerType = (ListenerType) args.getSerializable(ARG_LISTENER_TYPE);
switch (listenerType) {
case ACTIVITY: {
// Send callback events to the hosting activity
mListener = (DriverVehicleDialogListener) activity;
break;
}
case FRAGMENT: {
// Send callback events to the "target" fragment
mListener = (DriverVehicleDialogListener) getTargetFragment();
break;
}
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Button btnAddDriverVehicle = (Button) mView.findViewById(R.id.addDriverVehicleButton);
btnAddDriverVehicle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DatabaseHelper1 mOpenHelper = new DatabaseHelper1(getActivity());
try {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.delete("drivers", " driver_number = 70", null);
} catch (SQLException e) {
}
}
});
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Bundle args = getArguments();
int titleResource = args.getInt(ARG_TITLE_RESOURCE);
DialogType dialogType = (DialogType) args.getSerializable(ARG_DIALOG_TYPE);
if (args.containsKey(ARG_SET_DRIVER)) {
mDrivers = args.getLongArray(ARG_SET_DRIVER);
}
if (args.containsKey(ARG_SET_VEHICLE)) {
mVehicles = args.getLongArray(ARG_SET_VEHICLE);
}
mView = LayoutInflater.from(getActivity()).inflate(R.layout.driver_vehicle_dialog, null);
if ((dialogType == DialogType.DRIVER_SPINNER) || (dialogType == DialogType.DRIVER_VEHICLE_SPINNER)) {
driversSpinner = (Spinner) mView.findViewById(R.id.driversSpinner);
vehiclesSpinner = (Spinner) mView.findViewById(R.id.vehiclesSpinner);
driversSpinner.setVisibility(View.VISIBLE);
mDriversAdapter = new SimpleCursorAdapter(getActivity(), R.layout.driver_listview_row, null, new String[] { ConsoleContract.Drivers.DRIVER_NUMBER,
ConsoleContract.Drivers.DRIVER_NAME }, new int[] { R.id.driver_number, R.id.driver_name }, 0);
driversSpinner.setAdapter(mDriversAdapter);
driversSpinner.setOnItemSelectedListener(this);
}
if ((dialogType == DialogType.VEHICLE_SPINNER) || (dialogType == DialogType.DRIVER_VEHICLE_SPINNER)) {
vehiclesSpinner.setVisibility(View.VISIBLE);
mVehiclesAdapter = new SimpleCursorAdapter(getActivity(), R.layout.vehicle_listview_row, null, new String[] { ConsoleContract.Vehicles.VEHICLE_NUMBER,
ConsoleContract.Vehicles.VEHICLE_VIN }, new int[] { R.id.vehicle_number, R.id.vehicle_vin }, 0);
vehiclesSpinner.setAdapter(mVehiclesAdapter);
vehiclesSpinner.setOnItemSelectedListener(this);
}
// Prepare the loader. Either re-connect with an existing one, or start a new one.
getLoaderManager().initLoader(DRIVERS_LOADER, null, this);
getLoaderManager().initLoader(VEHICLES_LOADER, null, this);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(mView);
if (titleResource == 0) {
builder.setMessage("Select Driver and Vehicle");
} else {
builder.setMessage(getString(titleResource));
}
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mListener.onDialogPositiveClick(mDrivers, mVehicles);
}
});
builder.setNegativeButton(android.R.string.cancel, null);
return builder.create();
}
private static class DatabaseHelper1 extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "test.db";
private static final int DATABASE_VERSION = 1;
DatabaseHelper1(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
// These are the Contacts rows that we will retrieve.
static final String[] DRIVERS_SUMMARY_PROJECTION = new String[] { ConsoleContract.Drivers._ID, ConsoleContract.Drivers.DRIVER_ID, ConsoleContract.Drivers.DRIVER_NUMBER,
ConsoleContract.Drivers.DRIVER_NAME };
static final String[] VEHICLES_SUMMARY_PROJECTION = new String[] { ConsoleContract.Vehicles._ID, ConsoleContract.Vehicles.VEHICLE_ID, ConsoleContract.Vehicles.VEHICLE_NUMBER,
ConsoleContract.Vehicles.VEHICLE_VIN };
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
// First, pick the base URI to use depending on whether we are
// currently filtering.
Uri baseUri = null;
String select = null, sortOrder = null;
String[] projection = null;
switch (id) {
case DRIVERS_LOADER:
baseUri = ConsoleContract.Drivers.CONTENT_URI;
select = "((" + Drivers.DRIVER_NAME + " NOT NULL) AND (" + Drivers.DRIVER_NAME + " != '' ))";
sortOrder = Drivers.DRIVER_NUMBER;
projection = DRIVERS_SUMMARY_PROJECTION;
break;
case VEHICLES_LOADER:
baseUri = ConsoleContract.Vehicles.CONTENT_URI;
select = "((" + Vehicles.VEHICLE_NUMBER + " NOT NULL) AND (" + Vehicles.VEHICLE_NUMBER + " != '' ))";
sortOrder = Vehicles.VEHICLE_NUMBER;
projection = VEHICLES_SUMMARY_PROJECTION;
break;
}
return new CursorLoader(getActivity(), baseUri, projection, select, null, sortOrder);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
int id = loader.getId();
MatrixCursor newCursor = null;
switch (id) {
case DRIVERS_LOADER:
newCursor = new MatrixCursor(DRIVERS_SUMMARY_PROJECTION);
break;
case VEHICLES_LOADER:
newCursor = new MatrixCursor(VEHICLES_SUMMARY_PROJECTION);
break;
}
newCursor.addRow(new String[] { "0", "0", "", "" });
Cursor[] cursors = { newCursor, data };
Cursor mergedCursor = new MergeCursor(cursors);
switch (id) {
case DRIVERS_LOADER:
mDriversAdapter.swapCursor(mergedCursor);
break;
case VEHICLES_LOADER:
mVehiclesAdapter.swapCursor(mergedCursor);
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
int id = loader.getId();
switch (id) {
case DRIVERS_LOADER:
mDriversAdapter.swapCursor(null);
break;
case VEHICLES_LOADER:
mVehiclesAdapter.swapCursor(null);
break;
}
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (parent.getId() == R.id.driversSpinner) {
mDriver = id;
} else {
mVehicle = id;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}