Skip to main content
deleted 946 characters in body
Source Link
public class Profile implements Parcelable {
    private long mId;
    private String mName;

    public Profile(long id, String name) {
        mId = id;
        mName = name;
    }

    public Profile(Profile otherProfile) {
        otherProfile.mId = mId;
        otherProfile.mName = mName;
    }

    public long getId() {
        return mId;
    }
    
    public void setId(long id) {
        mId = id;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }
    
    @Override
    public int describeContents() {
        return 0; 
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mId);
        dest.writeString(mName);
    }

    private Profile(Parcel in) { 
        mId = in.readLong();
        mName = in.readString();
    }

    public static final Creator<Profile> CREATOR = new Creator<Profile>() {
        @Override
        public Profile createFromParcel(Parcel source) {
            return new Profile(source);
        }

        @Override
        public Profile[] newArray(int size) {
            return new Profile[size];
        }
    };

}
public class Profile implements Parcelable {
    private long mId;
    private String mName;

    public Profile(long id, String name) {
        mId = id;
        mName = name;
    }

    public Profile(Profile otherProfile) {
        otherProfile.mId = mId;
        otherProfile.mName = mName;
    }

    public long getId() {
        return mId;
    }
    
    public void setId(long id) {
        mId = id;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }
    
    @Override
    public int describeContents() {
        return 0; 
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mId);
        dest.writeString(mName);
    }

    private Profile(Parcel in) { 
        mId = in.readLong();
        mName = in.readString();
    }

    public static final Creator<Profile> CREATOR = new Creator<Profile>() {
        @Override
        public Profile createFromParcel(Parcel source) {
            return new Profile(source);
        }

        @Override
        public Profile[] newArray(int size) {
            return new Profile[size];
        }
    };

}
public class Profile {
    private long mId;
    private String mName;

    public Profile(long id, String name) {
        mId = id;
        mName = name;
    }

    public long getId() {
        return mId;
    }
    
    public void setId(long id) {
        mId = id;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }
   
}
Source Link

Properly structuring SQLite classes/operations in Android

I am new to Android development and I want to ensure I'm learning decent practices for doing things. Right now this is my database class, which currently allows me to make a new instance of the singleton, as well as create a profiles table, as well as add/retrieve from the profiles table.

This is my code so far:

public class DatabaseHelper extends SQLiteOpenHelper {
    private static volatile SQLiteDatabase mDatabase;
    private static DatabaseHelper mInstance = null;
    private static Context mContext;

    private static final String DB_NAME = "database.db";
    private static final int DB_VERSION = 1; 

    public static final String PROFILES_TABLE = "PROFILES";
    public static final String PROFILES_COLUMN_ID = "_ID";
    public static final String PROFILES_COLUMN_NAME = "NAME";

    private static final String DB_CREATE_PROFILES_TABLE =  
            "CREATE TABLE " + PROFILES_TABLE + " ("
                    + PROFILES_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
                    + PROFILES_COLUMN_NAME + " TEXT UNIQUE NOT NULL)";


    public static synchronized DatabaseHelper getInstance(Context context) {
       
        if (mInstance == null) {
            mInstance = new DatabaseHelper(context.getApplicationContext());
            try {
                mInstance.open();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return mInstance;
    }

    private DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DB_CREATE_PROFILES_TABLE);
    }

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

    @Override
    public void onConfigure(SQLiteDatabase db){
        super.onConfigure(db);
        db.setForeignKeyConstraintsEnabled(true);
    }

    public synchronized void open() throws SQLException {
        mDatabase = getWritableDatabase();
    }

    public synchronized void close() {
        mDatabase.close();
    }

    public synchronized long addNewProfile(String name) {
        ContentValues values = new ContentValues();
        values.put(DatabaseHelper.PROFILES_COLUMN_NAME, name);
        return mDatabase.insertWithOnConflict(DatabaseHelper.PROFILES_TABLE, null, values, SQLiteDatabase.CONFLICT_IGNORE);
    }

    public synchronized Profile getProfileById(long profileId) {
        Cursor cursor = mDatabase.query(
                DatabaseHelper.PROFILES_TABLE, // table
                new String[]{DatabaseHelper.PROFILES_COLUMN_ID, DatabaseHelper.PROFILES_COLUMN_NAME}, // column names
                DatabaseHelper.PROFILES_COLUMN_ID + " = ?", // where clause
                new String[]{profileId + ""}, // where params
                null, // groupby
                null, // having
                null);  // orderby
        cursor.moveToFirst();
        Profile profile = null;
        if (!cursor.isAfterLast()) {
            String profileName = getStringFromColumnName(cursor, DatabaseHelper.PROFILES_COLUMN_NAME);
            profile = new Profile(profileId, profileName);
            cursor.moveToNext();
        }
        cursor.close();
        return profile;
    }

    public synchronized List<Profile> getAllProfiles() {
        List<Profile> profiles = new ArrayList<>();
        Cursor cursor = mDatabase.query(
                DatabaseHelper.PROFILES_TABLE, // table
                new String[]{DatabaseHelper.PROFILES_COLUMN_ID, DatabaseHelper.PROFILES_COLUMN_NAME}, // column names
                null, // where clause
                null, // where params
                null, // groupby
                null, // having
                DatabaseHelper.PROFILES_COLUMN_NAME); // orderby
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            long profileId = getLongFromColumnName(cursor, DatabaseHelper.PROFILES_COLUMN_ID);
            String profileName = getStringFromColumnName(cursor, DatabaseHelper.PROFILES_COLUMN_NAME);
            profiles.add(new Profile(profileId, profileName));
            cursor.moveToNext();
        }
        cursor.close();
        return profiles;
    }

    private synchronized long getLongFromColumnName(Cursor cursor, String columnName) {
        int columnIndex = cursor.getColumnIndex(columnName);
        return cursor.getLong(columnIndex);
    }

    private synchronized String getStringFromColumnName(Cursor cursor, String columnName) {
        int columnIndex = cursor.getColumnIndex(columnName);
        return cursor.getString(columnIndex);
    }

}

For reference (this may or may not be necessary, but I am posting it just in case), my Profile class, which is something I use in several other places in the app:

public class Profile implements Parcelable {
    private long mId;
    private String mName;

    public Profile(long id, String name) {
        mId = id;
        mName = name;
    }

    public Profile(Profile otherProfile) {
        otherProfile.mId = mId;
        otherProfile.mName = mName;
    }

    public long getId() {
        return mId;
    }
    
    public void setId(long id) {
        mId = id;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }
    
    @Override
    public int describeContents() {
        return 0; 
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(mId);
        dest.writeString(mName);
    }

    private Profile(Parcel in) { 
        mId = in.readLong();
        mName = in.readString();
    }

    public static final Creator<Profile> CREATOR = new Creator<Profile>() {
        @Override
        public Profile createFromParcel(Parcel source) {
            return new Profile(source);
        }

        @Override
        public Profile[] newArray(int size) {
            return new Profile[size];
        }
    };

}

My questions:

  1. Is it proper to be storing the field names of the table in the database class like this, or should I be moving it to its own separate class (for example a ProfileSql class of some kind that holds all the names).

  2. Should I be decoupling the query logic from this class somehow? How do I do this? What if I have several tables, queries, thread methods, etc? Do these all go in their own separate classes, too? If I add CRUD functions for several tables, this class could get very large very quickly.

  3. Should I be somehow tying any of this stuff into my Profile class itself, which I use in several other places in my app? For instance should I be including the profile table SQL stuff (the create table string and the table/column names) in the Profile class, or is this meddling things together that shouldn't be?

As you can see I am mostly asking where stuff should go. Right now I am just kind of lumping it all together into one database class.

I am hoping that this example is short enough to where someone can show me the proper way to restructure all of this so I can take those skills and apply them going forward.