【问题标题】:ORMLite for Android: Bind DAO with RoboguiceORMLite for Android:将 DAO 与 Roboguice 绑定
【发布时间】:2011-04-22 03:08:41
【问题描述】:

我只是想用 ORMLite 设置我的 Android 项目。我正在使用 Roboguice 进行 DI。 现在我的问题是,这里是否有人可以帮助让他们一起工作。

我已经设置了扩展 OrmLiteSqliteOpenHelper 的助手类。现在我想知道如何注入正确的 DAO 类。

一般的最佳实践会很棒。由于使用 OrmLiteBaseActivity 不应该真正适用,因为这应该由 Roboguice 处理。问题只是:如何?

非常感谢您的帮助、您的经验、最佳实践等。

【问题讨论】:

  • 我有兴趣帮助@Sam7,但我不知道如何开始。如果您愿意,请直接与我联系 (256.com/gray/email) 并提供概述,我们可以看看是否可以解决。

标签: android ormlite roboguice


【解决方案1】:

如果您从 OrmLiteBaseActivity 扩展,您将无法从 RoboActivity 扩展。没关系,只需调用以下命令(假设 roboguice 1.1)对您的非机器人活动执行注入:

((InjectorProvider)getApplicationContext()).getInjector().injectMembers(this)

一旦你有了它,你就可以注入你的 dao 对象。

要注入您的 DAO,我建议您遵循 SystemServiceProvider 建立的模式(classbindings)。所以像下面这样实现一个 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;

【讨论】:

  • 谢谢伙计,非常感谢。
  • 只是一个让我大吃一惊的问题:上面代码中的 T 类型是您想要的 Dao 的数据对象,而不是自定义的 Dao 类型本身。
  • 我不想扩展基本活动,我想在 Application 对象中进行一次绑定。有什么指点吗?
【解决方案2】:

我遇到了同样的问题,最终创建了一个 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();

【讨论】:

  • 我认为你有更完整的解决方案。我为 OrmLite Helpers 编写了初始类,所以看到我自己的 cmets 很奇怪 ;) Android 中的类层次结构可能很粗糙。它很少见,但偶尔多重继承会很棒。实际上希望使用 mixins 或类似的结构。我今天有一个关于 Honeycomb 的教程,最近刚接触到 roboguice,我认为是时候重新审视 OrmLite 助手类了。单引用计数实例是可行的方法,但更容易集成到其他类层次结构中会很有用。
【解决方案3】:

这不是我想出的解决方案的最佳实践。

请留下备注以进行改进。

我在这里使用 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。 有什么意见吗?

【讨论】:

    【解决方案4】:

    http://abdennour-insat.blogspot.com/2012/10/using-ormlite-for-sqlite-with-android.html

    你可以按照这个教程。

    我使用了特定的软件架构来避免多重继承 我在tuto开头说:

    使用 ormlite 的类扩展

    OrmliteActivity 。但是当你使用 GreenDroid 时

    ,Activity 应该扩展 GDActivity。

    很遗憾,Java 不支持多个

    继承,即一个JAVA类只能扩展一个

    超类最大值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      相关资源
      最近更新 更多