Получение активности из контекста в android
У меня есть я в тупике.
Мне нужно вызвать метод активности из пользовательского класса макета. Проблема в том, что я не знаю, как получить доступ к активности из макета.
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);
}
}
Как вы можете видеть выше, я создаю программный профиль profileView и передаю его в ActivityContext. 2 вопроса:
- Я передаю правильный контекст в профиль?
- Как получить содержащую активность из контекста?
Ответы
Ответ 1
Из вашего Activity
просто перейдите в this
как Context
для вашего макета:
ProfileView pv = new ProfileView(this, null, temp, tempPd);
Впоследствии у вас будет Context
в макете, но вы узнаете, что это на самом деле ваш Activity
, и вы можете использовать его так, чтобы у вас было то, что вам нужно:
Activity activity = (Activity) context;
Ответ 2
В Android есть два разных контекста. Один для вашего приложения (пусть назовет его БОЛЬШОЙ) и по одному для каждого представления (позвольте назвать его контекстом активности).
Линейный Layout - это представление, поэтому вы должны вызвать контекст активности. Чтобы вызвать это из операции, просто вызовите "this". Так легко, не так ли?
Когда вы используете
this.getApplicationContext();
Вы вызываете контекст BIG, тот, который описывает ваше приложение и не может управлять вашим представлением.
Большая проблема с Android заключается в том, что контекст не может вызвать вашу активность. Это очень важно, чтобы избежать этого, когда кто-то начинает с разработки Android. Вы должны найти лучший способ закодировать свой класс (или заменить контекст контекста на "Активность активности" и при необходимости перевести его в "Контекст" ).
С уважением.
Просто чтобы обновить свой ответ. Самый простой способ получить Activity context
- определить экземпляр static
в Activity
. Например
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;
}
}
И затем, в ваших Task
, Dialog
, View
, вы можете использовать этот код для получения Activity context
:
if (DummyActivity.instance != null)
{
// Do your operations with DummyActivity.instance
}
Ответ 3
Это то, что я успешно использовал для преобразования Context
в Activity
при работе в пользовательском интерфейсе в фрагментах или пользовательских представлениях. Он будет рекурсивно распаковывать ContextWrapper или возвращать null, если он терпит неудачу.
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;
}
Ответ 4
Если вы хотите вызвать метод активности из собственного класса макета (класс без активности). Вы должны создать делегат, используя интерфейс.
Он не проверен, и я правильно его закодировал. но я передаю способ достижения желаемого.
Прежде всего создать и интерфейс
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");
}
}
И реализуйте это для любой операции.
и назовите его как
ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
pv.setCallBack(new TaskCompleteListener
{
public void onProfileClicked(String resultStringFromProfileView){}
});
Ответ 5
Контекст может быть приложением, службой, активностью и т.д.
Обычно контекст Views в Activity - это сама Activity, поэтому вы можете подумать, что можете просто передать этот контекст в Activity, но на самом деле вы не всегда можете это сделать, потому что контекст также может быть ContextThemeWrapper в этом случае.
ContextThemeWrapper сильно используется в последних версиях AppCompat и Android (благодаря атрибуту android: theme в макетах), поэтому я лично никогда не выполнил бы этот приведение.
Короткий ответ: вы не можете надежно получить активность из контекста в представлении. Передайте Activity в представление, вызвав метод на нем, который принимает параметр Activity as.
Ответ 6
Никогда не используйте getApplicationContext() с представлениями.
Он всегда должен быть контекстом активности, поскольку представление привязано к активности. Кроме того, у вас может быть собственный набор тем, и при использовании контекста приложения все теги будут потеряны. Подробнее о различных версиях контекстов здесь.
Ответ 7
Я использовал преобразование Activity
Activity activity = (Activity) context;
Ответ 8
Активность - это специализация Контекста, поэтому, если у вас есть Контекст, вы уже знаете, какую деятельность вы намереваетесь использовать, и можете просто перевести a в c; где a - это Activity и c - это контекст.
Activity a = (Activity) c;
Ответ 9
Этот метод должен быть полезным..!
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;
}
Я надеюсь, что это помогает.. Веселое кодирование!
Ответ 10
А в Котлине
tailrec fun Context.activity(): Activity? = when {
this is Activity -> this
else -> (this as? ContextWrapper)?.baseContext?.activity()
}