0

I am building an app that displays items in a ListFragment. Right now each item displays the title and creation date. There are two other fragments. One that creates an item and has a EditText field where i can edit the title. Another simply displays an individual items contents.

The issue I am having is that every time I enter a character in the EditText field the app closes. The error messages indicate that the error occurs at onTextChanged in the TextChangedListener. Since I had this feature working when I was storing everything as a JSON file the error must occur because of the way i am updating the database and updating my model layer.

This file performs all the database operations and creates a custom Cursor.

public class SnapDatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "FeedFragment";

private static final String DB_NAME = "snap.sqlite";
private static final int VERSION = 1;

private static final String TABLE_SNAP = "snap";

private static final String COLUMN_SNAP_ID = "_id";
private static final String COLUMN_SNAP_DATE = "snap_date";
private static final String COLUMN_SNAP_UUID = "snap_uuid";
private static final String COLUMN_SNAP_TITLE = "snap_title";

public SnapDatabaseHelper(Context context){
    super(context, DB_NAME, null, VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
    // Create SNAP table
    db.execSQL("create table snap(" + 
    "_id integer primary key autoincrement, " +
    //"snap_uuid text, " +
    "snap_date integer, " +
    "snap_title text) ");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // 
}

public long insertSnap(Snap snap){
    ContentValues cv = new ContentValues();
    //cv.put(COLUMN_SNAP_UUID, snap.getUniqueId().toString());
    cv.put(COLUMN_SNAP_DATE, snap.getDate().getTime());
    cv.put(COLUMN_SNAP_TITLE, "");
    return getWritableDatabase().insert(TABLE_SNAP, null, cv);

}
public boolean updateTitle(long snapId, String text)
{
 ContentValues cv = new ContentValues();
 cv.put(COLUMN_SNAP_ID, snapId);          
 cv.put(COLUMN_SNAP_TITLE, text);

 int i= getWritableDatabase().update(TABLE_SNAP, cv, COLUMN_SNAP_ID+ "=" + snapId, null);
 return i>0;
}
 public SnapCursor querySnap(long id) {
        Cursor wrapped = getReadableDatabase().query(TABLE_SNAP, 
                null, // all columns 
                COLUMN_SNAP_ID + " = ?", // look for a run ID
                new String[]{ String.valueOf(id) }, // with this value
                null, // group by
                null, // order by
                null, // having
                "1"); // limit 1 row
        return new SnapCursor(wrapped);
 }
 public SnapCursor querySnaps() {
        // equivalent to "select * from run order by start_date asc"
        Cursor wrapped = getReadableDatabase().query(TABLE_SNAP,
                null, null, null, null, null, COLUMN_SNAP_DATE + " asc");
        return new SnapCursor(wrapped);
    }

public static class SnapCursor extends CursorWrapper{
    public SnapCursor(Cursor c){
        super(c);
    }
    public Snap getSnap() {
        if (isBeforeFirst() || isAfterLast())
            return null;

        Snap s = new Snap();
        s.setId(getLong(getColumnIndex(COLUMN_SNAP_ID)));
        //s.setUniqueId(UUID(getString(getColumnIndex(COLUMN_SNAP_UUID))));
        s.setDate(new Date(getLong(getColumnIndex(COLUMN_SNAP_DATE))));
        s.setTitle(getString(getColumnIndex(COLUMN_SNAP_TITLE)));
        return s;
    }
}

}

This file links the fragments to the DatabaseHelper.

public class SnapLab {

private static SnapLab sSnapLab;
private Context mAppContext;
private SnapDatabaseHelper mHelper;

// private constructor
private SnapLab(Context appContext){
    mAppContext = appContext;
    mHelper = new SnapDatabaseHelper(mAppContext);
}
public static SnapLab get(Context c){
    if(sSnapLab == null){
        sSnapLab = new SnapLab(c.getApplicationContext());
    }
    return sSnapLab;
}
public Snap insertSnap() {
    Snap s = new Snap();
    s.setId(mHelper.insertSnap(s));

    return s;
}
public boolean updateTitle(long snapId, String text){


    return  mHelper.updateTitle(snapId, text);

}

public SnapCursor querySnaps() {
    return mHelper.querySnaps();
}

public Snap getSnap(long id) {
    Snap s = null;
    SnapCursor cursor = mHelper.querySnap(id);
    cursor.moveToFirst();
    // if we got a row, get a run
    if (!cursor.isAfterLast())
        s = cursor.getSnap();
    cursor.close();
    return s;
}

}

Here is the fragment with the EditText field

public class EditPageFragment extends Fragment {
private static final String TAG = "EditPageFragment";
public static final String EXTRA_SNAP_ID = "SNAP_ID";

private SnapLab mSnapLab;
private Snap mSnap;
private SnapDatabaseHelper mHelper;
private EditText mSnapText;
private Button mUploadButton;
private TextView mDateText;
private Long snapId;

public static EditPageFragment newInstance(Long snapId){
    Bundle args = new Bundle();
    args.putLong(EXTRA_SNAP_ID, snapId);
    EditPageFragment fragment = new EditPageFragment();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
    mSnapLab = SnapLab.get(getActivity());

    Bundle args = getArguments();
    if (args != null){
        long snapId = args.getLong(EXTRA_SNAP_ID, -1);
        if (snapId != -1){
            mSnap = mSnapLab.getSnap(snapId);
        }
    }
    mSnap = new Snap();
    mSnap = mSnapLab.insertSnap();
}   

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle   savedInstanceState){
    View v = inflater.inflate(R.layout.edit_fragment, parent, false);


    mDateText = (TextView)v.findViewById(R.id.edit_dateText);
    mDateText.setText(mSnap.getDate().toString());

    mSnapText = (EditText)v.findViewById(R.id.edit_snapText);
    mSnapText.addTextChangedListener(new TextWatcher(){
        @Override
        public void afterTextChanged(Editable s) {
            //leave blank for now
        }
        @Override
        public void beforeTextChanged(CharSequence c, int start, int count,
                int after) {
            //leave blank for now
        }
        @Override
        public void onTextChanged(CharSequence c, int start, int before,
                int count) {
            mSnap.setTitle(c.toString());
            mSnapLab.updateTitle(snapId, c.toString());

            Log.i(TAG, "text saved");
        }
    });

    return v;
}
}

The import bits of code are the updateTitle() functions. What could I be doing wrong. Do you have a suggestion on how to better update a database. Everything works great except for the updating of the title. I appreciate any bit of help.

4

1 回答 1

0

看起来 snapId 没有分配

private Long snapId; //field

几行之后

long snapId = args.getLong(EXTRA_SNAP_ID, -1); //local variable

几行之后

mSnapLab.updateTitle(snapId, c.toString()); //field

请下次添加堆栈跟踪。

于 2013-10-24T14:34:48.460 回答