从android中的上下文获取活动

时间:2012-03-27 14:16:54

标签: android android-layout android-activity view hierarchy

这个让我难过。

我需要在自定义布局类中调用activity方法。这个问题是我不知道如何从布局中访问活动。

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. 我是否将正确的上下文传递给Profileview?
  2. 如何从上下文中获取包含活动?

13 个答案:

答案 0 :(得分:438)

Activity开始,只需将[{1}}作为this传递给您的布局:

Context

之后你会在布局中找到ProfileView pv = new ProfileView(this, null, temp, tempPd); ,但你会知道它实际上是你的Context并且你可以施展它以便你拥有所需的东西:

Activity

答案 1 :(得分:28)

  1. 没有
  2. 你不能
  3. Android中有两种不同的上下文。一个用于您的应用程序(我们称之为BIG一个),每个视图一个(让我们称之为活动上下文)。

    linearLayout是一个视图,因此您必须调用活动上下文。要从活动中调用它,只需调用“this”即可。这很容易不是吗?

    使用时

    this.getApplicationContext();
    

    您调用BIG上下文,该上下文描述您的应用程序并且无法管理您的视图。

    Android的一个大问题是上下文无法调用您的活动。当有人开始使用Android开发时,这是一个很大的避免这个问题。你必须找到一种更好的方法来编写你的类(或者用“Activity activity”替换“Context context”,并在需要时将它转换为“Context”。

    问候。


    只是为了更新我的回答。获取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;
        }
    }
    

    然后,在您的TaskDialogView中,您可以使用这种代码来获取Activity context

    if (DummyActivity.instance != null)
    {
        // Do your operations with DummyActivity.instance
    }
    

答案 2 :(得分:26)

这是我在片段或自定义视图中在UI中操作时成功用于将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;
}

答案 3 :(得分:8)

  

如果您想从自定义布局类(非活动类)中调用活动方法。您应该使用interface创建委托。

未经测试,我编码正确。但我正在传达一种实现你想要的方式。

首先创建和界面

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){}
               });

答案 4 :(得分:6)

上下文可以是应用程序,服务,活动等。

通常,Activity中的Views的上下文是Activity本身,所以你可能认为你可以将这个Context强制转换为Activity但实际上你不能总是这样做,因为在这种情况下上下文也可以是ContextThemeWrapper。 / p>

ContextThemeWrapper在AppCompat和Android的最新版本中被大量使用(感谢布局中的android:theme属性)所以我个人永远不会执行此演员。

如此简短的回答是:您无法从视图中的上下文中可靠地检索活动。通过调用Activity上的方法将Activity传递给视图,该方法将Activity作为参数。

答案 5 :(得分:2)

永远不要将 getApplicationContext()与视图一起使用。

它应始终是活动的上下文,因为视图附加到活动。此外,您可能有自定义主题集,并且在使用应用程序的上下文时,所有主题都将丢失。阅读有关不同版本的上下文here的更多信息。

答案 6 :(得分:0)

一个Activity是Context的一个特化,所以,如果你有一个Context,你已经知道你打算使用哪个活动,只需将 一个 强制转换为 < EM> C ;其中 a 是一个活动, c 是一个上下文。

Activity a = (Activity) c;

答案 7 :(得分:0)

我使用了转换活动

Activity activity = (Activity) context;

答案 8 :(得分:0)

这种方法应该有用..!

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;

    }

我希望这有帮助..快乐编码!

答案 9 :(得分:0)

在科特林:

tailrec fun Context.activity(): Activity? = when {
  this is Activity -> this
  else -> (this as? ContextWrapper)?.baseContext?.activity()
}

答案 10 :(得分:0)

一些实时数据回调,

class ProfileView{
    private val _profileViewClicked = MutableLiveData<ProfileView>()
    val profileViewClicked: LiveData<ProfileView> = _profileViewClicked
}

class ProfileActivity{

  override fun onCreateView(...){

    profileViewClicked.observe(viewLifecycleOwner, Observer { 
       activityMethod()
    })
  }

}

答案 11 :(得分:0)

创建一个扩展函数。并使用您的上下文调用此扩展函数,例如 context.getActivity()。

fun Context.getActivity(): AppCompatActivity? {
      var currentContext = this
      while (currentContext is ContextWrapper) {
           if (currentContext is AppCompatActivity) {
                return currentContext
           }
           currentContext = currentContext.baseContext
      }
      return null
}

答案 12 :(得分:0)

对于 kotlin 用户 -

val activity = context as Activity