我只是想用 ORMLite 设置我的 Android 项目。我正在使用 Roboguice 进行 DI。现在我的问题是,这里是否有人可以帮助让他们一起工作。
我已经设置了我的助手类扩展OrmLiteSqliteOpenHelper
. 现在我想知道如何注入正确的 DAO 类。
一般的最佳实践会很棒。由于 usingOrmLiteBaseActivity
不应该真正适用,因为这应该由 Roboguice 处理。问题只是:如何?
我非常感谢任何帮助、您的经验、最佳实践等。
如果您从 OrmLiteBaseActivity 扩展,您将无法从RoboActivity扩展。没关系,只需调用以下命令(假设 roboguice 1.1)对您的非机器人活动执行注入:
((InjectorProvider)getApplicationContext()).getInjector().injectMembers(this)
一旦你有了它,你就可以执行你的 dao 对象的注入。
要注入您的 DAO,我建议您遵循 SystemServiceProvider(类和绑定)建立的模式。所以像下面这样实现一个 DaoProvider:
class DaoProvider<T> implements Provider<T> {
protected ConnectionSource conn;
protected Class<T> clazz;
public DaoProvider( ConnectionSource conn, Class<T> clazz ) {
this.conn = conn;
this.clazz = clazz;
}
@Override
public T get() {
return DaoManager.createDao( conn, clazz );
}
}
提供绑定。您需要为要注入的每种 DAO 类型执行一项操作:
bind(MyDaoObjectType.class).toProvider(
new DaoProvider<MyDaoObjectType>(conn,MyDaoObjectType.class));
然后您可以将其注入您的活动或其他任何地方:
@Inject MyDaoObjectType myDaoObjectType;
我遇到了同样的问题,最后创建了一个 OrmLiteActivityListener 来监听我的 RoboActivity 并处理它引发的事件。
public class RoboOrmActivityBase<H extends IOrmLiteSqliteOpenHelper> extends RoboActivity {
@Inject RoboOrmLiteActivityListener<H> OrmActivityListener;
/*
* Get a helper for this action.
*/
public H getHelper() {
return OrmActivityListener.getHelper();
}
/**
* Get a connection source for this action.
*/
public ConnectionSource getConnectionSource() {
return OrmActivityListener.getHelper().getConnectionSource();
}
}
RoboOrmLiteActivityListener 类派生自 OrmLiteActivityBase 类。我删除了它的继承并让它监听。
public class RoboOrmLiteActivityListener<H extends IOrmLiteSqliteOpenHelper> {
private volatile H helper;
private volatile boolean created = false;
private volatile boolean destroyed = false;
OrmLiteSqliteOpenHelperProvider databaseHelperProvider;
@Inject
public RoboOrmLiteActivityListener(OrmLiteSqliteOpenHelperProvider databaseHelperProvider) {
this.databaseHelperProvider = databaseHelperProvider;
}
/**
* Get a helper for this action.
*/
public H getHelper() {
if (helper == null) {
if (!created) {
throw new IllegalStateException("A call has not been made to onCreate() yet so the helper is null");
} else if (destroyed) {
throw new IllegalStateException(
"A call to onDestroy has already been made and the helper cannot be used after that point");
} else {
throw new IllegalStateException("Helper is null for some unknown reason");
}
} else {
return helper;
}
}
/**
* Get a connection source for this action.
*/
public ConnectionSource getConnectionSource() {
return getHelper().getConnectionSource();
}
// As you might expect, some events can have parameters. The OnCreate event
// has the savedInstanceState parameter that Android passes to onCreate(Bundle)
public void onCreate(@Observes OnCreateEvent onCreate) {
//Ln.d("onCreate savedInstanceState is %s", onCreate.getSavedInstanceState())
if (helper == null) {
helper = getHelperInternal();
created = true;
}
}
public void onDestroy(@Observes OnDestroyEvent onDestroy) {
releaseHelper(helper);
destroyed = true;
}
/**
* This is called internally by the class to populate the helper object instance. This should not be called directly
* by client code unless you know what you are doing. Use {@link #getHelper()} to get a helper instance. If you are
* managing your own helper creation, override this method to supply this activity with a helper instance.
*
* <p>
* <b> NOTE: </b> If you override this method, you most likely will need to override the
* {@link #releaseHelper(OrmLiteSqliteOpenHelper)} method as well.
* </p>
*/
private H getHelperInternal() {
@SuppressWarnings("unchecked")
H newHelper = (H) databaseHelperProvider.get();
return newHelper;
}
/**
* Release the helper instance created in {@link #getHelperInternal(Context)}. You most likely will not need to call
* this directly since {@link #onDestroy()} does it for you.
*
* <p>
* <b> NOTE: </b> If you override this method, you most likely will need to override the
* {@link #getHelperInternal(Context)} method as well.
* </p>
*/
private void releaseHelper(H helper) {
OpenHelperManager.releaseHelper();
helper = null;
}
}
然后我有一个 DatabaseHelperProvider,它提供了从 OrmLiteSqliteOpenHelper 扩展的 Helper。此提供程序在从 OpenHelperManager 检索到我的助手后手动对其执行注入。
public class OrmLiteSqliteOpenHelperProvider implements Provider<OrmLiteSqliteOpenHelper> {
private final Context context;
private final Injector injector;
@Inject
public OrmLiteSqliteOpenHelperProvider(Context context, Injector injector) {
this.context=context;
this.injector=injector;
}
public OrmLiteSqliteOpenHelper get() {
//The OpenHelperManager built the DatabaseHelper, not us. So we need to guice it up manually.
//Guice normally does its injections when it does its constructions.
OrmLiteSqliteOpenHelper dbhelp = OpenHelperManager.getHelper(context);
injector.injectMembers(dbhelp);
return dbhelp;
}
}
我还有一个名为 IOrmLiteSqliteOpenHelper 的接口,其中包含从 OrmLiteSqliteOpenHelper 中提取的成员。然后,当我为派生自 OrmLiteSqliteOpenHelper 的助手构建接口(IDatabaseHelper)时,我可以从 IOrmLiteSqliteOpenHelper 扩展。
然后在我的模块中绑定我有
static {
OpenHelperManager.setOpenHelperClass(DatabaseHelper.class);
}
和
@SuppressWarnings("unchecked")
private void bindDataHelperProvider() {
bind(IDatabaseHelper.class)
.toProvider((Class<? extends Provider<? extends IDatabaseHelper>>) OrmLiteSqliteOpenHelperProvider.class);
}
然后我的 Activity 将 RoboGuice 和 Ormlite 的所有内容完全在基类中处理,如下所示:
public class MyActivity extends RoboOrmActivityBase<IDatabaseHelper> {
List<IMyEntity> lis;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.routine);
try {
Dao<IMyEntity,Integer> myDao = getHelper().getMyDao();
lis = myDao.queryForAll();
这不是我提出的解决方案的最佳实践,它有效。
请留下备注以进行改进。
我在这里使用 UserLocation 实体作为示例要将 SqliteOpenHelper 和 Dao 绑定为单例,我将其添加到模块配置中:
bind(new TypeLiteral<SqliteOpenHelper>(){}).toProvider(OrmLiteSqliteOpenHelperProvider.class).in(Singleton.class);
bind(new TypeLiteral<Dao<UserLocation, Integer>>(){}).toProvider(DaoUserLocationProvider.class).in(Singleton.class);
OrmLiteSqliteOpenHelperProvider 看起来像这样:
public class OrmLiteSqliteOpenHelperProvider implements Provider<SqliteOpenHelper>
{
@Inject Context context;
@Override
public SqliteOpenHelper get() {
return (SqliteOpenHelper) OpenHelperManager.getHelper(context);
}
}
DaoUserLocationProvider 如下所示:
public class DaoUserLocationProvider implements Provider<Dao<UserLocation, Integer>>
{
@Inject SqliteOpenHelper sqliteOpenHelper;
@Override
public Dao<UserLocation, Integer> get() {
try {
return sqliteOpenHelper.getUserLocationDao();
} catch (SQLException e) {
Ln.e(e);
}
return null;
}
}
现在我可以这样注入道列克:
@Inject private Dao<UserLocation, Integer> userLocationDao;
这样我就可以继续使用 roboguice 活动,并且 SqliteOpenHelper 被 roboguice 保存为单例。
但是关于销毁/释放的问题仍然存在。我很想复制粘贴 OrmLiteBaseActivity 的内容并扩展 RoboActivity。有什么意见吗?
http://abdennour-insat.blogspot.com/2012/10/using-ormlite-for-sqlite-with-android.html
你可以按照这个教程。
我使用了特定的软件架构来避免多重继承,我在 tuto 开头说:
使用 ormlite 的类扩展
OrmliteActivity 。但是当你使用 GreenDroid
,Activity 应该扩展 GDActivity 。
不幸的是,Java 不支持多个
继承,即一个JAVA类只能扩展一个
超类最大值。