ORMLite для Android: связывайте DAO с Roboguice - PullRequest
8 голосов
/ 22 апреля 2011

Я просто пытаюсь настроить мой проект Android с ORMLite. Я использую Roboguice для DI. Теперь у меня вопрос, может ли кто-нибудь здесь помочь тем, кто работает вместе.

Я установил расширение моего вспомогательного класса OrmLiteSqliteOpenHelper. Теперь мне интересно, как ввести правильный класс DAO.

Общая лучшая практика была бы фантастической. Поскольку использование OrmLiteBaseActivity на самом деле не должно применяться, так как это должно обрабатываться Roboguice. Вопрос просто: как?

Я очень ценю любую помощь, ваш опыт, лучшие практики и т. Д.

Ответы [ 4 ]

12 голосов
/ 25 апреля 2011

Если вы расширяете с OrmLiteBaseActivity, вы не сможете расширить с RoboActivity . Это нормально, просто позвоните по следующему пункту (при условии, что roboguice 1.1), чтобы выполнить инъекцию вашей активности, не связанной с робоактивностью:

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

Как только вы это сделаете, вы можете выполнить инъекцию ваших дао объектов.

Чтобы внедрить ваши DAO, я предлагаю вам следовать шаблону, установленному SystemServiceProvider ( class и bindings ). Поэтому реализуйте 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;
3 голосов
/ 29 мая 2011

У меня была такая же проблема, и я в итоге создал 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, который предоставляет мой Helper, который выходит из OrmLiteSqliteOpenHelper. Этот провайдер вручную выполняет инъекцию моего помощника после извлечения его из 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. Затем, когда я создаю свой интерфейс (IDatabaseHelper) для моего помощника, который происходит от OrmLiteSqliteOpenHelper, я могу расширяться от IOrmLiteSqliteOpenHelper.

Тогда для привязки в моем модуле у меня есть

static {
    OpenHelperManager.setOpenHelperClass(DatabaseHelper.class);
}

и

@SuppressWarnings("unchecked")
private void bindDataHelperProvider() {
    bind(IDatabaseHelper.class)
    .toProvider((Class<? extends Provider<? extends IDatabaseHelper>>) OrmLiteSqliteOpenHelperProvider.class);
}

Тогда в моей Деятельности все для 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();
1 голос
/ 28 апреля 2011

Это не лучшая практика, просто решение, которое я придумала, которое работает.

Пожалуйста, оставьте заметки для улучшений.

Я использую сущность 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.Есть мнения?

0 голосов
/ 28 октября 2012

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

вы можете следовать этому туто.

Я использовал специальную программную архитектуру, чтобы избежать множественного наследования. Я говорю в начале tuto:

Класс, который использует ormlite, расширяет

OrmliteActivity. Но когда вы используете GreenDroid

, Действия должны расширять GDActivity.

К сожалению, Java не поддерживает множественное наследование

, т. Е. Класс JAVA может расширять только один максимум

суперкласса.

...