最近開發(fā)的項目中需要使用到ORM框架蛮寂,但是我并不想針對每一個具體業(yè)務寫一個Dao轧苫,對于通用的CRUD功能捆交,我想試著通過一個BaseDao解決問題焕蹄,這里涉及到一個關鍵問題是:如何在編譯時獲取泛型的實際類型逾雄?后來通過抽象類解決了這個問題。
封裝
public abstract class BaseDao<T> {
protected static DaoSession daoSession;
public BaseDao(Context context) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, dbPath, null);
Database db = helper.getWritableDb();
daoSession = new DaoMaster(db).newSession();
}
public void insert(final T t) {
// 延遲處理異常,所以這里不在構造器中初始化rxDao
try {
final RxDao<T, Void> rxDao = (RxDao<T, Void>) daoSession.getDao(Class.forName(getGenericClassName())).rx();
new Thread(new Runnable() {
@Override
public void run() {
// 當調(diào)用訂閱操作(即調(diào)用Observable.subscribe()方法)的時候腻脏,被觀察者才真正開始發(fā)出事件鸦泳。
// 核心源碼見Observable類的create(OnSubscribe<T> f)方法的解釋
rxDao.insert(t).subscribe(new Subscriber<T>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
if (e != null){
e.printStackTrace();
}
}
@Override
public void onNext(T t) {
}
});
}
}).start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void update(final T t) {
try {
final RxDao<T, Void> rxDao = (RxDao<T, Void>) daoSession.getDao(Class.forName(getGenericClassName())).rx();
new Thread(new Runnable() {
@Override
public void run() {
rxDao.update(t).subscribe(new Subscriber<T>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
if (e != null){
e.printStackTrace();
}
}
@Override
public void onNext(T t) {
}
});
}
}).start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void delete(final T t) {
try {
final RxDao<T, Void> rxDao = (RxDao<T, Void>) daoSession.getDao(Class.forName(getGenericClassName())).rx();
new Thread(new Runnable() {
@Override
public void run() {
rxDao.delete(t).subscribe(new Subscriber<Void>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
if (e != null){
e.printStackTrace();
}
}
@Override
public void onNext(Void aVoid) {
}
});
}
}).start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void loadAll(final ColDaoCallBack<T> colDaoCallBack) {
try {
final RxDao<T, Void> rxDao = (RxDao<T, Void>) daoSession.getDao(Class.forName(getGenericClassName())).rx();
new Thread(new Runnable() {
@Override
public void run() {
rxDao.loadAll()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(colDaoCallBack.getAction1(), new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
if (throwable != null){
throwable.printStackTrace();
}
}
});
}
}).start();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public final Type getType() {
Type superType = getClass().getGenericSuperclass();
Type type = ((ParameterizedType) superType).getActualTypeArguments()[0];
return type;
}
public final String getGenericClassSimpleName() {
String raw = getType().toString();
int spaceIndex = raw.lastIndexOf(" ");
int spotIndex = raw.lastIndexOf(".");
int dollarIndex = raw.lastIndexOf("$");
int index = Math.max(Math.max(spaceIndex, spotIndex), dollarIndex);
String result = raw.substring(index + 1);
return result;
}
public final String getGenericClassName() {
String raw = getType().toString();
int spaceIndex = raw.lastIndexOf(" ");
String result = raw.substring(spaceIndex + 1);
return result;
}
}
實際使用的時候需要創(chuàng)建一個匿名內(nèi)部類的實例來繼承BaseDao抽象類,但是由于CRUD的操作已經(jīng)在BaseDao中具體實現(xiàn)了永品,但是只需要提供一個空實現(xiàn)即可做鹰,同時傳入實際的泛型類型。
具體使用
Bean bean = new Bean();
BaseDao<Bean> baseDao = new BaseDao<>(context){};
baseDao.insert(bean);