2011-04-22 12 views
8

Solo intento configurar mi Android Project con ORMLite. Estoy usando Roboguice para DI. Ahora mi pregunta es si alguien aquí puede ayudar a conseguir que trabajen juntos.ORMLite para Android: Enlace DAO con Roboguice

He configurado mi clase de ayuda que se extiende OrmLiteSqliteOpenHelper. Ahora me pregunto cómo inyectar la clase DAO correcta.

Una buena práctica general sería fantástica. Ya que usar OrmLiteBaseActivity no debería aplicarse realmente, ya que Roboguice debería manejarlo. La pregunta es justa: ¿cómo?

Me gustaría mucho agradecería cualquier ayuda, su experiencia, mejores prácticas, etc.

+1

Estaría interesado en ayudar @ Sam7, pero no estoy seguro de cómo empezar. Si está preparado, contácteme directamente (http://256.com/gray/email/) con una descripción general y podemos ver si podemos resolverlo. – Gray

Respuesta

12

Si se extiende desde OrmLiteBaseActivity, usted no será capaz de extenderse desde RoboActivity. Eso está bien, simplemente llame al (suponiendo roboguice 1.1) después de realizar la inyección en su actividad no roboactivity:

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

Una vez que tenga eso, se puede realizar la inyección de los objetos DAO.

Para inyectar sus DAO, le sugiero que siga el patrón establecido por SystemServiceProvider (class y bindings). Así que implemente un DaoProvider como el siguiente:

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 ); 
    } 
} 

Suministre los enlaces. Tendrá que hacer una para cada tipo de DAO desea inyectar: ​​

bind(MyDaoObjectType.class).toProvider(
     new DaoProvider<MyDaoObjectType>(conn,MyDaoObjectType.class)); 

A continuación, se puede inyectar en su actividad o en cualquier otro lugar:

@Inject MyDaoObjectType myDaoObjectType; 
+0

Gracias amigo, muy apreciado. – Sam7

+0

Solo un problema que me hizo tropezar: el tipo de T en el código de arriba es el objeto de datos del Dao, no el tipo personalizado de Dao. – Diederik

+0

No quiero extender la actividad base, y quiero hacer mis enlaces una vez en el objeto Aplicación. ¿Alguna sugerencia? –

1

Esto no es una buena práctica sólo el solución que he encontrado, eso funciona.

Deje las notas para las mejoras.

estoy usando una entidad UserLocation aquí como ejemplo Para enlazar SqliteOpenHelper y Dao como simple, he añadido esto a la configuración del módulo:

bind(new TypeLiteral<SqliteOpenHelper>(){}).toProvider(OrmLiteSqliteOpenHelperProvider.class).in(Singleton.class); 
bind(new TypeLiteral<Dao<UserLocation, Integer>>(){}).toProvider(DaoUserLocationProvider.class).in(Singleton.class); 

El OrmLiteSqliteOpenHelperProvider se ve así:

public class OrmLiteSqliteOpenHelperProvider implements Provider<SqliteOpenHelper> 
{ 
    @Inject Context context; 

    @Override 
    public SqliteOpenHelper get() { 
     return (SqliteOpenHelper) OpenHelperManager.getHelper(context); 
    } 
} 

El DaoUserLocationProvider tiene este aspecto:

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; 
    } 
} 

Ahora puedo simplemente inyectar el Dao liek esto:

@Inject private Dao<UserLocation, Integer> userLocationDao; 

De esa manera puedo seguir usando la actividad roboguice y la SqliteOpenHelper se mantiene como un producto único por roboguice.

Pero la pregunta en la destrucción/liberar restos. Estoy tentado de copiar solo pegar el contenido de OrmLiteBaseActivity y extender RoboActivity. ¿Alguna opinión?

3

tenía este mismo problema y terminó creando un OrmLiteActivityListener, a escuchar mi RoboActivity y controlar los eventos que plantea.

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(); 
} 
} 

clase RoboOrmLiteActivityListener se deriva de la clase OrmLiteActivityBase. Quité su herencia y la hice escuchar en su lugar.

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; 
} 
} 

entonces tengo una DatabaseHelperProvider que proporciona mi ayudante que se extiende desde OrmLiteSqliteOpenHelper. Este proveedor realiza manualmente la inyección en mi asistente después de recuperarlo de 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; 
    } 
} 

I también tienen una interfaz llamada IOrmLiteSqliteOpenHelper, que contiene miembros extraídos de OrmLiteSqliteOpenHelper. Luego, cuando construyo mi interfaz (IDatabaseHelper) para mi helper que se deriva de OrmLiteSqliteOpenHelper, puedo extender desde IOrmLiteSqliteOpenHelper.

Luego de unirse en mi Módulo tengo

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

y

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

Entonces mi actividad ha de muebles para el RoboGuice y Ormlite manejado enteramente en la clase base y se parece a esto:

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(); 
+0

Creo que tiene la solución más completa. Escribí las clases iniciales para OrmLite Helpers, así que fue raro ver mis propios comentarios;) La jerarquía de clases en Android puede ser difícil. Su herencia rara, pero en ocasiones múltiple sería fantástica. En realidad, deseando mixins o estructura similar.Tuve un tutorial hoy en Honeycomb, y recientemente ingresé en roboguice, y creo que es hora de volver a visitar las clases de ayuda de OrmLite en general. La única instancia contada de referencia es el camino a seguir, pero sería más fácil la integración en otras jerarquías de clase. –

0

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

Puedes seguir este tuto.

que utiliza una arquitectura de software específico para evitar la herencia múltiple digo al inicio del tuto:

la clase que utiliza ormlite extiende

OrmliteActivity .Pero cuando se utiliza GreenDroid

, Actividades shuld extender GDActivity.

Desafortunadamente, Java no soporta herencia múltiple

, es decir, una clase Java puede extender sólo un

superclase máxima.