Usando getResources () en la clase sin actividad

123

Estoy tratando de usar el método getResources en una clase sin actividad. ¿Cómo obtengo la referencia al objeto "recursos" para poder acceder al archivo xml almacenado en la carpeta de recursos?

Ejemplo:

XmlPullParser xpp = getResources().getXml(R.xml.samplexml);
ssk
fuente
Normalmente no es una buena idea pasar Contextobjetos en Android. Puede conducir a pérdidas de memoria. Vea mi respuesta para una solución menos arriesgada.
Jason Crosby
posible duplicado de ¿Cómo recuperar un contexto de una clase sin actividad?
Richard Le Mesurier

Respuestas:

147

Tendrá que pasarle un contextobjeto. O bien thissi tiene una referencia a la clase en un activty, ogetApplicationContext()

public class MyActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        RegularClass regularClass = new RegularClass(this);
    }
}

Luego puede usarlo en el constructor (o establecerlo en una variable de instancia):

public class RegularClass(){
    private Context context;

    public RegularClass(Context current){
        this.context = current;
    }

    public findResource(){
        context.getResources().getXml(R.xml.samplexml);
    }
}

Donde el constructor acepta Contextcomo parámetro

LuckyLuke
fuente
77
Normalmente no es una buena idea pasar Contextobjetos en Android. Puede conducir a pérdidas de memoria.
Jason Crosby
28
Como regla básica, claro, pero creo que esto es algo engañoso. Contextlos objetos son desagradables porque no es obvio de inmediato si abarca toda la aplicación o la actividad. Se producen pérdidas de memoria (y bloqueos) cuando se suministra el incorrecto. Por ejemplo, el suministro Activityde un objeto estático que necesita ay Contextdicho objeto no se destruye cuando Activityse lleva a Activitypersistir después de onDestroy, ya que no se puede GC debido a este otro objeto estático. Entonces, sí, puede ser peligroso, pero saber por qué es peligroso, creo que es importante mencionarlo aquí.
Dororo
2
^ Dororo, este es uno de los comentarios más importantes que he leído. El uso apropiado del contexto rara vez se discute. ¡Tengo la sensación de que he tenido muchos errores inexplicables por eso!
Jonathan Dunn
@Dororo ¿Tienes alguna sugerencia de práctica? ¿Deberíamos tratar de evitar pasar variables de contexto? Entonces, ¿qué podemos hacer cuando necesitamos alguna API de la clase de actividad?
Alston
35

No es una buena idea pasar Contextobjetos. Esto a menudo conducirá a pérdidas de memoria. Mi sugerencia es que no lo hagas. He creado numerosas aplicaciones de Android sin tener que pasar el contexto a las clases sin actividad en la aplicación. Una mejor idea sería obtener los recursos a los que necesita acceder mientras está en el Activityo Fragment, y conservarlo en otra clase. Luego puede usar esa clase en cualquier otra clase en su aplicación para acceder a los recursos, sin tener que pasar Contextobjetos.

Jason Crosby
fuente
Este es un buen consejo, gracias. ¿Sería un problema en un SQLiteOpenHelper? En el constructor, tienes que pasar un contexto. Ya no está disponible en los otros métodos, pero podría almacenarlo en un campo privado.
Peter
2
@ Peter Sí, hay algunas clases que requieren que pase en un objeto de contexto. Por lo tanto, es mejor tratar de usar solo esas clases como SqLiteOpenHelper en una actividad o fragmento para que no tenga que pasar por el objeto de contexto. Si es inevitable, solo asegúrese de establecer su referencia al objeto de contexto en nulo cuando haya terminado para ayudar a reducir el riesgo de pérdidas de memoria.
Jason Crosby
1
Pasar el objeto de contexto no siempre es malo, siempre y cuando pueda monitorear el ciclo de vida de la actividad. Si no es así, mejor use el contexto de la aplicación en lugar del contexto de la actividad usando getApplicationContext () para evitar pérdidas de memoria. Consulte stackoverflow.com/questions/7144177/… para recuperar el contexto de la aplicación.
FrozenFire
14

Hay una forma más sin crear un objeto también. Verifique la referencia . Gracias por @cristian. A continuación agrego los pasos que se mencionan en la referencia anterior. Para mí no me gusta crear un objeto para eso y acceder. Así que intenté acceder al getResources()sin crear un objeto. Encontré esta publicación. Entonces pensé agregarlo como respuesta.

Siga los pasos para acceder getResources()en una clase sin actividad a without passing a contexttravés del objeto.

  • Cree una subclase de Application, por ejemplo public class App extends Application {. Consulte el código al lado de los pasos.
  • Establezca el android:nameatributo de su <application>etiqueta en AndroidManifest.xmlpara apuntar a su nueva clase, por ejemploandroid:name=".App"
  • En el onCreate()método de la instancia de su aplicación, guarde su contexto (p this. Ej. ) En un campo estático denominado appy cree un método estático que devuelva este campo, p getContext(). Ej .
  • Ahora puede usar: App.getContext()cuando quiera obtener un contexto, y luego podemos usar App.getContext().getResources()para obtener valores de los recursos.

Así es como debería verse:

public class App extends Application{

    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }

    public static Context getContext(){
        return mContext;
    }
}
Mahendran Sakkarai
fuente
5

Aquí está mi respuesta:

public class WigetControl {
private Resources res;

public WigetControl(Resources res) 
{
    this.res = res;
}

public void setButtonDisable(Button mButton)
{
    mButton.setBackgroundColor(res.getColor(R.color.loginbutton_unclickable));
    mButton.setEnabled(false);
}

}

y la llamada puede ser así:

        WigetControl control = new WigetControl(getResources());
        control.setButtonDisable(btNext);
lizlalala
fuente
3

esto se puede hacer usando

context.getResources().getXml(R.xml.samplexml);
ARAsha
fuente
Bueno, esto hizo la magia por mí. Gracias @ARAsha
Kenny Dabiri
pasar Contextobjetos no es una práctica saludable
Vemuri Pavan
3

Podemos usar el contexto como este intente ahora Donde el padre es el ViewGroup.

Context context = parent.getContext();
Jaydip Umaretiya
fuente
1

bueno, no hay necesidad de pasar el contexto y hacer todo eso ... simplemente haz esto

Context context = parent.getContext();

Editar: donde padre es el ViewGroup

Ankit Srivastava
fuente
3
Espero que haya sido rechazado por suponer que hay una variable de miembro conveniente 'ViewGroup parent'. Bastante estúpido supuesto.
Arnt
1

Esto siempre funciona para mí:

import android.app.Activity;
import android.content.Context;

public class yourClass {

 Context ctx;

 public yourClass (Handler handler, Context context) {
 super(handler);
    ctx = context;
 }

 //Use context (ctx) in your code like this:
 XmlPullParser xpp = ctx.getResources().getXml(R.xml.samplexml);
 //OR
 final Intent intent = new Intent(ctx, MainActivity.class);
 //OR
 NotificationManager notificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
 //ETC...

}

No relacionado con esta pregunta, pero ejemplo usando un Fragmento para acceder a los recursos / actividades del sistema como este:

public boolean onQueryTextChange(String newText) {
 Activity activity = getActivity();
 Context context = activity.getApplicationContext();
 returnSomething(newText);
 return false;
}

View customerInfo = getActivity().getLayoutInflater().inflate(R.layout.main_layout_items, itemsLayout, false);
 itemsLayout.addView(customerInfo);
Elroy
fuente
1

En la aplicación de guía turística del curso básico ANdroid de Udacity, he usado el concepto de Fragmentos. Me quedé atrapado por un tiempo experimentando dificultades para acceder a algunos recursos de cadena descritos en cadenas, archivo xml. Finalmente obtuve una solución.

Esta es la clase de actividad principal.

paquete com.example.android.tourguidekolkata;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState)
{
  //lines of code
   //lines of code
    //lines of code
    YourClass adapter = new YourClass(getSupportFragmentManager(), getApplicationContext()); 
    //lines of code
    // getApplicationContext() method passses the Context of main activity to the class TourFragmentPageAdapter 
}
}

Esta es la clase no Activity que extiende FragmentPageAdapter

public class YourClass extends FragmentPagerAdapter {
private String yourStringArray[] = new String[4];
Context context;

public YourClass (FragmentManager fm, Context context)
{
    super(fm);
    this.context = context; // store the context of main activity
    // now you can use this context to access any resource 
    yourStringArray[0] = context.getResources().getString(R.string.tab1);
    yourStringArray[1] = context.getResources().getString(R.string.tab2);
    yourStringArray[2] = context.getResources().getString(R.string.tab3);
    yourStringArray[3] = context.getResources().getString(R.string.tab4);
}
@Override
public Fragment getItem(int position)
 {
 }
@Override
public int getCount() {
return 4;
}

@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return yourStringArras[position];
}
}
Satadru Saha
fuente
0

En clase simple, declare el contexto y obtenga datos del archivo de la carpeta res

public class FileData
{
      private Context context;

        public FileData(Context current){
            this.context = current;
        }
        void  getData()
        {
        InputStream in = context.getResources().openRawResource(R.raw.file11);
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        //write stuff to get Data

        }
}

En la clase de actividad declara así

public class MainActivity extends AppCompatActivity 
{
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        FileData fileData=new FileData(this);
     }

}
sagar
fuente
0

Llego tarde pero la solución completa: Clase de ejemplo, contexto de uso como este: -

public class SingletonSampleClass {

    // Your cute context
    private Context context;
    private static SingletonSampleClass instance;

  // Pass as Constructor
    private SingletonSampleClass(Context context) {
        this.context = context;
    }

    public synchronized static SingletonSampleClass getInstance(Context context) {
        if (instance == null) instance = new SingletonSampleClass(context);
        return instance;
    }

//At end, don't forgot to relase memory
    public void onDestroy() {
       if(context != null) {
          context = null; 
       }
    }
}

Advertencia (Fugas de memoria)

¿Cómo resolver esto?

Opción 1 : en lugar de pasar el contexto de actividad, es decir, esto a la clase singleton, puede pasar applicationContext ().

Opción 2: si realmente tiene que usar el contexto de actividad, cuando la actividad se destruya, asegúrese de que el contexto que pasó a la clase singleton esté establecido en nulo.

Espero que ayude ...

Amit101320
fuente
0

en su actividad principal:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(ResourcesHelper.resources == null){
             ResourcesHelper.resources = getResources();
        }
    }
}

Recursos Ayudante:

public class ResourcesHelper {
    public static Resources resources;
}

luego úsalo en todas partes

String s = ResourcesHelper.resources.getString(R.string.app_name);
Hamid fadili
fuente