2012-04-17 8 views
12

Quiero crear una tabla hash estática Tabla hash para convertir cadenas a enteros. La advertencia aquí es que quiero usar cadenas Definí como recursos en varias listas en archivos XML.¿Es posible obtener recursos dentro de un bloque de contexto estático?

soy capaz de escribir esto, el uso de identificadores únicos recursos:

public class MyActivity extends Activity { 

private static Map<Integer, Integer> views = new HashMap<Integer, Integer>(); 
static { 
    views.put(R.string.full_text, MessageTable.VIEW_FULL); 
    views.put(R.string.only_text, MessageTable.VIEW_MSG); 
    views.put(R.string.tag_text, MessageTable.VIEW_TAGMSG); 
} 

me sale ningún error, pero lo que realmente necesita hacer es algo como esto:

public class MyActivity extends Activity { 

private static Map<String, Integer> views = new HashMap<String, Integer>(); 
static { 
    views.put(getResources().getString(R.string.full_text), MessageTable.VIEW_FULL); 
    views.put(getResources().getString(R.string.only_text), MessageTable.VIEW_MSG); 
    views.put(getResources().getString(R.string.tag_text), MessageTable.VIEW_TAGMSG); 
} 

que da mí el siguiente error en Eclipse:

Cannot make a static reference to the non-static method getResources() from the type ContextWrapper 

el mensaje tiene sentido, pero lo que no tiene sentido i s que los recursos son inalcanzables desde el bloque estático, uno pensaría que las variables estáticas se crearon a medida para hacer uso de los recursos.
Supongo que puedo llenar la tabla Hash durante el constructor del objeto, pero esto significaría hacerlo en el lugar equivocado.

+0

¿Por qué quieres cargar todo eso en un mapa hash? ¿No estaría bien simplemente hacer referencia al recurso y cargarlo en una cadena cuando la necesite de forma no estática? Supongo que no entiendo completamente la aplicación. – shibbybird

Respuesta

11

getResources() (abreviatura de ~ MyActivity.this.getResources()) requiere un objeto de contexto que no se inicializa en ese momento. Como el contexto solo está disponible después de presionar onCreate, no puede hacerlo en el momento de la construcción MyActivity.

La razón es que el administrador de actividades que instancia su clase MyActivity tiene que determinar la configuración (orientación, tamaño de pantalla, idioma, ...) antes de saber qué recursos deben extraerse del xml. -> Los recursos no son estáticos y no se puede acceder desde el contexto estático.

Así que supongo que no hay forma de evitar hacer esas operaciones en onCreate o posterior.

Editar: Mientras que usted puede actualizar el HashMap estática (o una estática Context) de onCreate No recomendaría que, dado que puede tener varias instancias de la misma actividad con posiblemente diferentes configuraciones/cambiantes. También almacenar un Context estático es una gran manera de crear un Memory Leak

+0

Creo que los recursos son los elementos más estáticos en una aplicación. De lo contrario, ¿cómo se explica que acceder a R.string.stringname está bien? Recibo tu explicación sobre por qué hay un error, espero que alguien sepa un bypass para llegar a las cuerdas. – ilomambo

+1

esas cosas 'R.whatever' son creadas por las herramientas de compilación de android en tiempo de compilación. Son solo identidades "internas" que se refieren a tus recursos. El contenido real que se recupera para esa identificación se determina en función de la configuración. Esto es necesario ya que puede/debe tener múltiples definiciones para la misma ID, p. Cadenas en 'res/values ​​/ strings.xml',' res/values-es/strings.xml', 'res/values-land-mdpi/strings.xml' – zapl

+0

Mantener el contexto de la aplicación no puede provocar la pérdida de memoria. Sin embargo, mantener un contexto específico puede. – asenovm

0

Siempre puede mantener una referencia estática al ApplicationContext. Una forma posible se describe aquí: Static way to get 'Context' on Android?

+0

Igual que el anterior, en su enlace el contexto se establece solo durante onCreate(). Necesito los recursos de inmediato para construir el mapa, tal vez antes de onCreate(). – ilomambo

+0

Pero me hiciste pensar y realmente tengo una pregunta similar relacionada, ¿Puedes definir un mapa en XML? Si esto es posible, entonces seguramente tengo mis recursos disponibles en el archivo XML. Creo que lo publicaré como una nueva pregunta, ya que merece su propia publicación. – ilomambo

0

No sé cuál es la MEJOR manera, pero, por ejemplo, en mi aplicación, tengo un Singleton (llamado GuiaUtil) que siempre mantiene mi Actividad y Contexto actuales.

private static Map<String, Integer> views = new HashMap<String, Integer>(); 
static { 
views.put(GuiaUtil.instance().getAppContext().getResources().getString(R.string.full_text), MessageTable.VIEW_FULL); 
views.put(GuiaUtil.instance().getAppContext().getResources().getString(R.string.only_text), MessageTable.VIEW_MSG); 
views.put(GuiaUtil.instance().getAppContext().getResources().getString(R.string.tag_text), MessageTable.VIEW_TAGMSG); 
} 
+0

¿Es este un código similar al suyo que realmente funciona? Porque me parece que debería obtener un error para getAppContext(), ya que es posible que el contexto aún no se haya configurado cuando se ejecuta este bloque estático. – ilomambo

+0

Si buscas ponerlo en tu primera actividad, probablemente no funcione porque todavía no has configurado el Singleton ... como ya he dicho, obviamente no es la mejor manera de hacerlo, pero es un comienzo. De todos modos, puedes crear tu HashMap estático en la comprobación "onCreate" si no es nulo antes de que lo hagas. –

1

Una cosa que puede hacer es crear una clase Application y registrarlo en su AndroidManifest.xml. A continuación, anule el método onCreate y establezca la clase Application como referencia estática y luego toque la clase Activity para ejecutar el inicializador estático. La clase Application se ejecutará cuando la aplicación se cargue en la memoria para que siempre se ejecute antes de cualquier Activity.

Existen algunos inconvenientes importantes para esto.El más obvio que pienso es si el lenguaje del sistema cambia y usted ha agregado traducciones a estos recursos; entonces tendrá cadenas incoherentes porque la aplicación utilizará el idioma por defecto/sea cual sea el idioma cuando se lanzó la aplicación. Los recursos de cadenas están influenciados por el sistema de administración de recursos de Android, por lo que los cambios en cosas como la orientación, el lenguaje del sistema, las dimensiones de la pantalla pueden influir en cuáles son estos valores. Esa es la razón por la cual las Actividades se reinician cuando

En resumen, es mejor utilizar pares de valor-clave de Cuerdas constantes para este trabajo. Si necesita utilizar recursos de cadena para que pueda manejar mejor las traducciones. Los cargaba cada vez que comienza la actividad. De lo contrario, corre el riesgo de pérdidas de memoria y traducciones de cadenas inconsistentes.

public MyApplication extends Application { 

    public static Context GlobalContext = null; 

    @Override 
    protected void onCreate() { 
    MyApplication.GlobalContext = this; 

    // Touch the activity class. 
    MyActivity activity = new MyActivity(); 
    // Throw it away by not using it. 

    // invalidate handle to prevent GC leaks. 
    GlobalContext = null; 
    } 
} 

public class MyActivity extends Activity { 
    private static Map<String, Integer> views = new HashMap<String, Integer>(); 

    static { 
    Context context = MyApplication.GlobalContext; 
    Resources res = context.getResources(); 
    views.put(res.getString(R.string.full_text), MessageTable.VIEW_FULL); 
    views.put(res.getString(R.string.only_text), MessageTable.VIEW_MSG); 
    views.put(res.getString(R.string.tag_text), MessageTable.VIEW_TAGMSG); 
    } 
} 
+0

Te entiendo. La situación no es la que esperaba, pero tendré que trabajar con lo que tengo a mano. Gracias – ilomambo

4
public Static Resources mResources; 
public MyApplication extends Application 
{ 
    @Override 
    public void onCreate() 
    { 
      mResources = getResources(); 
    } 

} 

Una vez que tenga la referencia estática a los recursos, se puede hacer referencia a ella en cualquier lugar de toda la aplicación. Sin embargo, no estoy seguro de si esto va a introducir una fuga de mamá o no;

Cuestiones relacionadas