Получение активности из контекста в 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()
}