2012-06-27 13 views
38

A menudo me resulta necesario acceder a los métodos que requieren referenciar alguna actividad. Por ejemplo, para usar getWindowManager, necesito acceder a alguna actividad. Pero a menudo mi código para usar estos métodos está en alguna otra clase que no tiene referencia a una actividad. Hasta ahora, he almacenado una referencia a la actividad principal o pasado el contexto de alguna actividad a la clase. ¿Hay alguna forma mejor de hacer esto?Cómo hacer referencia a la actividad actual o principal de otra clase

+0

+1 ¡Esta es una gran pregunta! Este es un problema que tienen muchos desarrolladores: ¿Cómo averiguo cuál es la actividad que se está ejecutando (o "arriba")? –

+8

Mi opinión personal es que apesta que Google no haya hecho un método simple de API para acceder a la actividad actualmente activa independientemente de dónde se encuentre en el código. Después de todo, Android sabe de qué se trata y lo sigue. ¿Por qué no ser amable con el resto de nosotros los chicos pobres y dejarnos entrar :-( – AndroidDev

+0

si necesita algunos métodos a través de todas sus actividades que hacen simplemente lo mismo, no sería mejor crear una clase abstracta ¿Qué implementa todos estos métodos y deja que tus actividades se deriven de él? ¿O te equivoco? – herom

Respuesta

11

Pasar contexto es una mejor manera para la actividad Refrencia.

Puede pasar el contexto a otra clase.

en la actividad ::

AnotherClass Obj = new AnotherClass(this); 

en otra clase

class AnotherClass{ 

public AnotherClass(Context Context){ 

    } 

} 
+0

Pero si hay varias actividades cargadas, solo una de ellas estará activa en cualquier momento, entonces sospecho que hay un método para acceder a cualquier curre nt actividad es sin tener que pasar por un contexto. – AndroidDev

+1

Por favor, explique por qué es esta una mejor manera? – Slawa

2

Hay muchas maneras de comunicación Actividades.

que puede utilizar:

  • la startActivityForResult método

  • un sistema de mensaje de difusión y el receptor (que puede transmitir un evento de la actividad real, y registrar un receptor en la actividad de destino. Recuerde que la actividad de destino debe inicializarse previamente y no finalizarse)

  • como usted dice, almacene una referencia de la actividad de destino donde lo necesite.
+1

No quiero comunicación. Solo una referencia – AndroidDev

5

Puede implementar los métodos necesarios en su actividad e implementar un Handler. Luego, simplemente pase una instancia de controlador a sus clases, donde puede obtener un mensaje para el controlador y enviarlo al destino.

+0

Si voy a hacer eso, también podría pasar el contexto de la actividad a la clase. – AndroidDev

0

la manija de la Intención en la clase que usted quiere hacer estos métodos, y enviar su información a la misma en un paquete de este modo:

Intent i = new Intent("android.intent.action.MAIN"); 
    i.setComponent(new ComponentName("com.my.pkg","com.my.pkg.myActivity")); 
    Bundle data = new Bundle(); 

    i.putExtras(data); 

    startActivityForResult(i); 

Después, utilice un OnActivityResultListener para agarrar los nuevos datos.

+0

No, eso no es lo que estoy buscando. Todo lo que quiero es una referencia a cualquiera que sea la actividad actual, o la principal. Puede hacer que una clase llame a una clase y profundizar bastante. No debería haber una necesidad de pasar un contexto a cada clase. – AndroidDev

3

Puede hacerte instancia de la aplicación de un producto único, y lo utilizan cuando se necesita un Contexto

Un ejemplo es en esta pregunta:
Android Application as Singleton

De esta manera, cuando se necesita un contexto, se puede conseguirlo con
Context context = MyApplication.getInstance()

Esto podría no ser la solución más limpia, pero ha funcionado bien para mí hasta ahora

+0

Nunca funcionaría si estaba escribiendo las clases y se las di a alguien que no podría usar Singleton. – AndroidDev

+0

Eso es cierto ... :( –

-3

Es solo una suposición, ya que no he hecho esto, pero podría funcionar.

1) Obtenga su applicationContext haciendo que su clase de Aplicación de Android sea Singleton.

2) Obtenga su clase ActivityManager del contexto.

3) Obtenga una lista de RunningTaskInfos utilizando getRunningTasks() en el ActivityManager.

4) Obtenga el primer elemento RunningTaskInfo de la lista que debería ser la tarea más reciente iniciada.

5) Llame a topActivity en ese RunningTaskInfo que debe devolverle la actividad principal en la pila de actividades para esa tarea.

Ahora, esto parece MUCHO más trabajo que cualquiera de los otros métodos mencionados aquí, pero probablemente pueda encapsular esto en una clase estática y simplemente llamarlo cada vez que lo desee. Parece que podría ser la única forma de obtener la actividad principal en la pila sin agregar referencias a las actividades.

+0

¿Por qué el voto a favor? Una explicación sería agradable ... – onit

+0

No le di el voto a favor, pero ... uno de los problemas con esta técnica es que necesita permisos para getRunningTasks() y eso asusta a muchos usuarios. –

+0

@DavidWasser Es cierto, no recomiendo este enfoque, pero lo publiqué más para mostrar qué tipo de trabajo necesitaría realizar para sacar la actividad actualmente en ejecución de la pila sin un Referencia: – onit

1

Creamos un marco para esto. Tenemos una clase BaseActivity que hereda de Activity y reemplaza todos los métodos del ciclo de vida y tiene algunas variables estáticas (de clase) que hacen un seguimiento de la pila de actividades. Si algo quiere saber cuál es la actividad actual, simplemente llama a un método estático en BaseActivity que devuelve la actividad en la parte superior de nuestra pila administrada de forma privada.

Es un poco hacky, pero funciona. No estoy seguro de que lo recomendaría sin embargo.

10

Si ya tiene un contexto válido, sólo tiene que utilizar esto: Activity activity = (Activity) context;

+0

A menos que el contexto sea la aplicación, en cuyo caso se generará una ClassCastException. – nasch

+1

Sí, no siempre funciona, debe asegurarse de que lo que está emitiendo es efectivamente una Actividad o tendrá a ClassCastException. Para hacer eso, puede hacer "if (context instanceOf Activity) {// proceda a enviar}" –

+0

@ AleMuzzi, me salvó el tiempo .Gracias +1 vo te for u –

0

Soy nuevo en Android para que mi sugerencia puede parecer Guffy pero lo que si usted acaba de crear una referencia a su actividad como privada propiedad y asignar eso en el método OnCreate? Incluso puede crear su CustomActivity con OnCreate así y derivar todas sus actividades de su CustomActivity, no actividad genérica provista por adroid.

class blah extends Activity{ 
 
    private Activity activityReference; 
 
    public void onCreate(Bundle savedInstanceState) { 
 
     super.onCreate(savedInstanceState); 
 
     activityReference = this; 
 
    } 
 

 
}
después de que usted podría utilizar que la manera deseada, es decir, en

Intent i = new Intent(activityReference, SomeOtherActivity.class) 

etc

3

he encontrado una manera de obtener la actividad de una clase no actividad que No he visto discutido en foros. Esto fue después de numerosos intentos fallidos de usar getApplicationContext() y de pasar el contexto como un parámetro a los constructores, ninguno de los cuales dio actividad. Vi que mis adaptadores estaban echando el contexto de entrada a la actividad, así que hice el mismo reparto a mis constructores de clase no-actividad:

public class HandleDropdown extends Application{ 
... 
    public Activity activity; 
... 
public HandleDropdown() { 
    super(); 
} 
public HandleDropdown(Activity context) { 
    this.activity = context; 
    this.context = context; 
} 
public void DropList(View v,Activity context) { 
    this.activity = context; 
    this.context = context; 
... 
} 

Después de hacer esta conversión elenco de Contexto de actividad que podría utilizar dondequiera que this.activity necesitaba un contexto de Actividad.

0

Resolví esto haciendo que una clase singleton tenga una instancia de la clase a continuación como miembro.

public class InterActivityReferrer <T> { 
    HashMap<Integer, T> map; 
    ArrayList<Integer> reserve; 

    public InterActivityReferrer() { 
     map = new HashMap<>(); 
     reserve = new ArrayList<>(); 
    } 

    public synchronized int attach(T obj) { 
     int id; 
     if (reserve.isEmpty()) { 
      id = reserve.size(); 
     } 
     else { 
      id = reserve.remove(reserve.size() - 1); 
     } 

     map.put(id, obj); 
     return id; 
    } 

    public synchronized T get(int id) { 
     return map.get(id); 
    } 

    public synchronized T detach(int id) { 
     T obj = map.remove(id); 
     if (obj != null) reserve.add(id); 
     return obj; 
    } 
} 

Esta clase puede obtener un objeto T y devolver un entero único asignado al objeto mediante attach(). Los enteros asignados no colisionarán entre ellos a menos que HashMap falle. Cada entero asignado se liberará cuando su objeto correspondiente sea separado por detach(). Los enteros liberados se reutilizarán cuando se adjunte un nuevo objeto.

Y a partir de una clase singleton:

public class SomeSingleton { 
    ... 
    private InterActivityReferrer<Activity> referrer = new InterActivityReferrer<>(); 
    ... 
    public InterActivityReferrer<Activity> getReferrer() {return referrer;} 
} 

Y a partir de una actividad que necesita ser derivado:

... 
    int activityID = SomeSingleton.getInstance().getReferrer().attach(this); 
    ... 

Ahora, con esto, se devuelve un entero único que corresponde a esta instancia de actividad. Y un entero puede ser entregado en otra actividad inicial usando Intent y putExtra().

... 
    Intent i = new Intent(this, AnotherActivity.class); 
    i.putExtra("thisActivityID", activityID); 
    startActivityForResult(i, SOME_INTEGER); 
    ... 

Y de la otra actividad:

... 
    id refereeID = getIntent().getIntExtra("thisActivityID", -1); 
    Activity referredActivity = SomeSingleton.getInstance().getReferrer().get(refereeID); 
    ... 

Y por último, la actividad puede ser referido. Y InterActivityReferrer se puede usar para cualquier otra clase.

Espero que esto ayude.

0
public static Activity getLaunchActivity() 
{ 
    final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread"); 

    final Method methodApp = activityThreadClass.getMethod("currentApplication"); 
    App = (Application) methodApp.invoke(null, (Object[]) null); 
    Intent launcherIntent = App.getPackageManager().getLaunchIntentForPackage(App.getPackageName()); 
    launchActivityInfo = launcherIntent.resolveActivityInfo(App.getPackageManager(), 0); 
    Class<?> clazz; 
    try 
    { 
     clazz = Class.forName(launchActivityInfo.name); 
     if(clazz != null) 
      return Activity.class.cast(clazz.newInstance()); 
    } 
    catch (Exception e) 
    {} 

    return null; 
} 
+1

Agregue alguna explicación de lo que está haciendo su código. –

Cuestiones relacionadas