Extends from my previous post Retrofit 2 + AutoValueGson, I’m trying to add a database for the project. I choose to use ContentProvider due to the benefit of ContentObserver, with the help of SQLDelight to generate all the necessary fields in Java model.
I first create an User.sq
file under src/main/sqldelight/{package}/User.sq
, it will generated as UserModel.java
interface file under {package}
package.
CREATE TABLE IF NOT EXISTS user (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
login TEXT NOT NULL,
id INTEGER NOT NULL,
avatarUrl TEXT,
UNIQUE (login) ON CONFLICT REPLACE
);
drop_table:
DROP TABLE IF EXISTS user;
selectAll:
SELECT *
FROM user;
insertRow:
INSERT INTO user(login, id, avatarUrl)
VALUES (?, ?, ?);
Then I rename UserBean
.
@AutoValue
public abstract class UserBean {
public abstract String login();
public abstract int id();
@Nullable
public abstract String avatarUrl();
public static UserModel create(String login, int id, @Nullable String avatarUrl) {
return new AutoValue_UserModel(login, id, avatarUrl);
}
public static TypeAdapter<UserModel> typeAdapter(Gson gson) {
return new AutoValue_UserModel.GsonTypeAdapter(gson);
}
}
Change it to User implements UserModel
.
@AutoValue
public abstract class User implements UserModel {
public static final Factory<User> FACTORY = new Factory<>(
(_id, login, id, avatarUrl) -> new AutoValue_User(null, login, id, avatarUrl));
public static final RowMapper<User> SELECT_ALL_MAPPER = FACTORY.selectAllMapper();
public static TypeAdapter<User> typeAdapter(Gson gson) {
return new AutoValue_User.GsonTypeAdapter(gson);
}
public ContentValues asContentValues() {
return new Marshal(this).asContentValues();
}
}
In order to create or drop a table, it can simply call to User.CREATE_TABLE
or User.DROP_TABLE
.
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "app.db";
private static final int DATABASE_VERSION = 1;
private static DatabaseHelper instance;
public static DatabaseHelper getInstance(Context context) {
if (instance == null) {
instance = new DatabaseHelper(context.getApplicationContext());
}
return instance;
}
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(User.CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(User.DROP_TABLE);
onCreate(db);
}
}
For select record from a table, it can use UserModel.Mapper#map(Cursor)
to convert an Cursor
to User
.
For insert record into a table, it can use UserModel.Marshal#asContentValues()
to convert an User
to ContentValues
.
public class SqlBriteHelper {
private final ContentResolver contentResolver;
private final BriteContentResolver briteResolver;
@Inject
public SqlBriteHelper(ContentResolver contentResolver) {
this.contentResolver = contentResolver;
this.briteResolver = new SqlBrite.Builder()
.build()
.wrapContentProvider(contentResolver, Schedulers.io());
}
public Observable<List<User>> getUserList() {
return briteResolver.createQuery(User.CONTENT_URI, null, null, null, null, false)
.mapToList(User.SELECT_ALL_MAPPER::map);
}
public Observable<List<User>> setUserList(List<User> userList) {
return Observable.defer(() -> {
for (User user : userList) {
contentResolver.insert(User.CONTENT_URI, user.asContentValues());
}
return Observable.just(userList);
});
}
}
The full project can be found at GitHub.