developer - layout left of android
Obteniendo actividad del contexto en Android (9)
Este me tiene perplejo.
Necesito llamar a un método de actividad desde dentro de una clase de diseño personalizado. El problema con esto es que no sé cómo acceder a la actividad desde dentro del diseño.
ProfileView
public class ProfileView extends LinearLayout
{
TextView profileTitleTextView;
ImageView profileScreenImageButton;
boolean isEmpty;
ProfileData data;
String name;
public ProfileView(Context context, AttributeSet attrs, String name, final ProfileData profileData)
{
super(context, attrs);
......
......
}
//Heres where things get complicated
public void onClick(View v)
{
//Need to get the parent activity and call its method.
ProfileActivity x = (ProfileActivity) context;
x.activityMethod();
}
}
ProfileActivity
public class ProfileActivityActivity extends Activity
{
//In here I am creating multiple ProfileViews and adding them to the activity dynamically.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.profile_activity_main);
}
public void addProfilesToThisView()
{
ProfileData tempPd = new tempPd(.....)
Context actvitiyContext = this.getApplicationContext();
//Profile view needs context, null, name and a profileData
ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
profileLayout.addView(pv);
}
}
Como puede ver arriba, estoy instanciando el profileView programáticamente y pasando el activityContext con él. 2 preguntas:
- ¿Paso el contexto correcto a la vista de perfil?
- ¿Cómo obtengo la actividad que contiene el contexto?
Si desea llamar a un método de actividad desde dentro de una clase de diseño personalizado (clase no activa). Debe crear un delegado utilizando la interfaz.
No está probado y lo codifiqué bien. pero estoy transmitiendo una forma de lograr lo que quieres.
En primer lugar, crea e interfaz
interface TaskCompleteListener<T> {
public void onProfileClicked(T result);
}
public class ProfileView extends LinearLayout
{
private TaskCompleteListener<String> callback;
TextView profileTitleTextView;
ImageView profileScreenImageButton;
boolean isEmpty;
ProfileData data;
String name;
public ProfileView(Context context, AttributeSet attrs, String name, final ProfileData profileData)
{
super(context, attrs);
......
......
}
public setCallBack( TaskCompleteListener<String> cb)
{
this.callback = cb;
}
//Heres where things get complicated
public void onClick(View v)
{
callback.onProfileClicked("Pass your result or any type");
}
}
E impleméntalo en cualquier Actividad.
y llámalo como
ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
pv.setCallBack(new TaskCompleteListener
{
public void onProfileClicked(String resultStringFromProfileView){}
});
- No
- No puedes
Hay dos contextos diferentes en Android. Uno para su aplicación (llamémoslo GRANDE) y uno para cada vista (llamémoslo contexto de actividad).
Un lineLayout es una vista, por lo que debe llamar al contexto de la actividad. Para llamarlo desde una actividad, simplemente llame "this". Tan fácil, ¿verdad?
Cuando usas
this.getApplicationContext();
Llama al contexto GRANDE, el que describe su aplicación y no puede administrar su vista.
Un gran problema con Android es que un contexto no puede llamar a tu actividad. Eso es un gran problema para evitar esto cuando alguien comienza con el desarrollo de Android. Debe encontrar una mejor manera de codificar su clase (o reemplazar "Contexto contextual" por "Actividad actividad" y convertirlo en "Contexto" cuando sea necesario).
Saludos.
Solo para actualizar mi respuesta. La forma más fácil de obtener su Activity context
es definir una instancia static
en su Activity
. Por ejemplo
public class DummyActivity extends Activity
{
public static DummyActivity instance = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Do some operations here
}
@Override
public void onResume()
{
super.onResume();
instance = this;
}
@Override
public void onPause()
{
super.onPause();
instance = null;
}
}
Y luego, en su Task
, Dialog
, View
, podría usar ese tipo de código para obtener su Activity context
:
if (DummyActivity.instance != null)
{
// Do your operations with DummyActivity.instance
}
Desde tu Activity
, solo pasa this
como el Context
para tu diseño:
ProfileView pv = new ProfileView(this, null, temp, tempPd);
Luego, tendrá un Context
en el diseño, pero sabrá que en realidad es su Activity
y puede convertirlo para que tenga lo que necesita:
Activity activity = (Activity) context;
El contexto puede ser una Aplicación, un Servicio, una Actividad, y más.
Normalmente, el contexto de Vistas en una actividad es la Actividad misma, por lo que puede pensar que puede simplemente convertir este contexto en Actividad, pero en realidad no siempre puede hacerlo, porque el contexto también puede ser ContextThemeWrapper en este caso.
ContextThemeWrapper se usa mucho en las versiones recientes de AppCompat y Android (gracias al atributo android: theme en los diseños), así que personalmente nunca realizaría este elenco.
Entonces, la respuesta corta es: no se puede recuperar de manera confiable una Actividad de un Contexto en una Vista. Pase la Actividad a la vista llamando a un método que toma la Actividad como parámetro.
Este método debería ser útil ..!
public Activity getActivityByContext(Context context){
if(context == null){
return null;
}
else if((context instanceof ContextWrapper) && (context instanceof Activity)){
return (Activity) context;
}
else if(context instanceof ContextWrapper){
return getActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}
Espero que esto ayude ... ¡Feliz codificación!
Esto es algo que he utilizado con éxito para convertir Context
a Activity
cuando se opera dentro de la UI en fragmentos o vistas personalizadas. Descomparará ContextWrapper recursivamente o devolverá nulo si falla.
public Activity getActivity(Context context)
{
if (context == null)
{
return null;
}
else if (context instanceof ContextWrapper)
{
if (context instanceof Activity)
{
return (Activity) context;
}
else
{
return getActivity(((ContextWrapper) context).getBaseContext());
}
}
return null;
}
Utilicé la actividad de conversión
Activity activity = (Activity) context;
una Actividad es una especialización de Contexto, entonces, si tiene un Contexto, ya sabe qué actividad pretende usar y simplemente puede convertirlo en c ; donde a es una actividad y c es un contexto.
Activity a = (Activity) c;
Nunca use getApplicationContext () con vistas.
Siempre debe ser el contexto de la actividad, ya que la vista se adjunta a la actividad. Además, puede tener un conjunto de temas personalizado y, al usar el contexto de la aplicación, se perderán todos los temas. Lea más sobre las diferentes versiones de contextos here .