从android中的上下文获取活动

OVE*_*ONE 169 android view hierarchy android-layout android-activity

这个让我难过.

我需要在自定义布局类中调用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您在上面所看到的,我以编程方式实例化profileView并使用它传递activityContext.2个问题:

  1. 我将正确的上下文传递给Profileview吗?
  2. 如何从上下文中获取包含活动?

Bor*_*jev 453

从你的Activity,只是通过在this作为Context您的布局:

ProfileView pv = new ProfileView(this, null, temp, tempPd);
Run Code Online (Sandbox Code Playgroud)

之后你将有一个Context布局,但你会知道它实际上是你的Activity,你可以投射它,以便你有你需要的东西:

Activity activity = (Activity) context;
Run Code Online (Sandbox Code Playgroud)

  • 您无法保证您正在使用的上下文是活动上下文或应用程序上下文.尝试将应用程序上下文传递给DialogView,观察它崩溃,您将看到差异. (49认同)
  • 鲍里斯,问题是询问是否有办法从上下文中获取活动.这是不可能的.当然你可以演员,但这是最后的选择.如果要将Context视为活动,则不要向下转换为活动.它使代码更简单,并且在其他人维护代码时更不容易出错. (5认同)
  • 请注意,'getApplicationContext()'而不是'this'将不起作用. (5认同)

Man*_*oba 31

  1. 没有
  2. 你不能

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

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

当你使用

this.getApplicationContext();
Run Code Online (Sandbox Code Playgroud)

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

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

问候.


只是为了更新我的答案.获得你的最简单方法Activity contextstatic在你的中定义一个实例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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在你的Task,Dialog,View,你可以使用的代码,那种让你Activity context:

if (DummyActivity.instance != null)
{
    // Do your operations with DummyActivity.instance
}
Run Code Online (Sandbox Code Playgroud)

  • 创建对Activity的静态引用是创建内存泄漏的最佳方法. (11认同)
  • +1用于解释两种不同类型的上下文之间非常常见的混淆区域(就像有两个不同的`R`s).谷歌人需要丰富他们的词汇量. (4认同)
  • BTW,@ BorisStrandjev是正确的:**2.是的你可以**.(不能与工作代码争论) (3认同)
  • 不是真的.如果上下文是应用程序上下文,那么您的应用程序将崩溃. (2认同)

The*_*heo 28

这是我在片段或自定义视图中在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;
}
Run Code Online (Sandbox Code Playgroud)


Xar*_*mer 8

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

它未经测试,我编码正确.但我正在传达一种方法来实现你想要的.

首先是创建和接口

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

并将此实现到任何Activity.

并称之为

ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
pv.setCallBack(new TaskCompleteListener
               {
                   public void onProfileClicked(String resultStringFromProfileView){}
               });
Run Code Online (Sandbox Code Playgroud)


Bla*_*der 6

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

通常,Activity中的Views的上下文是Activity本身,因此您可能认为您可以将此Context转换为Activity,但实际上您不能总是这样做,因为在这种情况下,Context也可以是ContextThemeWrapper.

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

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


rjr*_*rjr 6

在 Kotlin 中:

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