【问题标题】:How to reference the current or main activity from another class如何从另一个类引用当前或主要活动
【发布时间】:2012-06-28 23:12:02
【问题描述】:

我经常发现自己需要访问需要引用某些活动的方法。例如,要使用getWindowManager,我需要访问一些Activity。但通常我使用这些方法的代码在其他一些没有引用活动的类中。到目前为止,我要么存储了对主要活动的引用,要么将某些活动的上下文传递给了类。有没有更好的方法来做到这一点?

【问题讨论】:

  • +1 这是个好问题!这是很多开发者都会遇到的一个问题:如何确定当前正在运行(或“top”)的 Activity 是什么?
  • 我个人的看法是,谷歌没有创建一个简单的 API 方法来访问当前活动的活动,无论你在代码中的哪个位置,这很糟糕。毕竟,Android 知道它是什么并跟踪它。为什么不对我们这些可怜的男孩好一点,让我们参与进来:-(
  • 如果您在所有活动中都需要一些方法,而这些方法只是做同样的事情,那么创建一个实现所有这些方法并让您的活动从中派生的抽象类不是更好吗?还是我误会了?
  • herom,你不应该费心去创造任何东西。如果 Android 知道当前 Activity 是什么,它应该很容易地引用它。
  • 很抱歉这个(也许是愚蠢的)问题,但我想不出我需要这个的情况。你能给我一个提示,或者描述你需要这个的情况(只是为了清理东西,所以我可以理解你想做什么)?提前致谢!

标签: android android-activity android-context


【解决方案1】:

如果您已经有一个有效的上下文,只需使用这个: Activity activity = (Activity) context;

【讨论】:

  • 除非上下文恰好是应用程序,在这种情况下会导致 ClassCastException。
  • 是的,它并不总是有效,您必须确保您所投射的内容实际上是一个 Activity,否则您将遇到 ClassCastException。为此,您可以执行“if(context instanceOf Activity){ // 继续转换 }”
  • @AleMuzzi 你节省了我的时间。谢谢 +1 投票给你
  • @AndroidDev 请考虑将此答案标记为正确
【解决方案2】:

传递上下文是引用 Activity 的更好方法。

您可以将 Context 传递给另一个类。

IN 活动 ::

AnotherClass Obj  = new AnotherClass(this);

在另一个班级

class AnotherClass{

public AnotherClass(Context Context){

    }

}

【讨论】:

  • 但是如果加载了多个活动,则其中只有一个会在任何时候处于活动状态,所以我怀疑有一种方法可以访问当前活动的任何内容,而无需传递上下文。
  • 请解释为什么这是一个更好的方法?
【解决方案3】:

您可以在活动中实现必要的方法并实现Handler。然后,只需将处理程序实例传递给您的类,您可以在其中获取处理程序的消息并将其发送到目标。

【讨论】:

  • 如果我要这样做,我不妨将活动的上下文传递给类。
【解决方案4】:

您可以将应用程序实例设为单例,并在需要上下文时使用它

这个问题中有一个例子:
Android Application as Singleton

这样,当你需要一个Context的时候,你可以通过
Context context = MyApplication.getInstance()得到它

这可能不是最干净的解决方案,但到目前为止它对我来说效果很好

【讨论】:

  • 如果我正在编写课程并将它们交给无法使用单例的其他人,那将永远无法工作。
【解决方案5】:

我是 android 新手,所以我的建议可能看起来很笨拙,但是如果您只是创建一个对您的活动的引用作为私有属性并在 OnCreate 方法中分配它呢?您甚至可以像这样使用 OnCreate 创建您的 CustomActivity,并从您的 CustomActivity 派生所有活动,而不是由 adnroid 提供的通用 Activity。

class blah extends Activity{
  private Activity activityReference;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityReference = this;
    }

}
之后你可以按照你想要的方式使用它,即在
Intent i = new Intent(activityReference, SomeOtherActivity.class)

【讨论】:

    【解决方案6】:

    我找到了一种将 Activity 带到我在论坛中没有讨论过的非 Activity 类的方法。这是在多次尝试使用 getApplicationContext() 并将上下文作为参数传递给构造函数的失败之后,这些尝试都没有提供 Activity。我看到我的适配器将传入的上下文转换为 Activity,所以我对我的非活动类构造函数进行了相同的转换:

    public class HandleDropdown extends Application{
    ...
        public Activity activity;
    ...
    public HandleDropdown() {
        super();
    }
    public HandleDropdown(Activity context) {
        this.activity = context;
        this.context = context;
    }
    public void DropList(View v,Activity context) {
        this.activity = context;
        this.context = context; 
    ...
    }
    

    在将 Context 转换为 Activity 之后,我可以在任何需要 Activity 上下文的地方使用 this.activity。

    【讨论】:

      【解决方案7】:

      Activity 的沟通方式有很多种。

      你可以使用:

      • startActivityForResult 方法

      • 广播消息和接收者系统(可以从实际活动中广播一个事件,并在目标活动中注册接收者。记住目标活动必须事先初始化且未完成)

      • 如您所说,将目标活动的引用存储在您需要的任何位置。

      【讨论】:

        【解决方案8】:

        我们为此构建了一个框架。我们有一个从Activity 继承的BaseActivity 类,它覆盖了所有生命周期方法,并具有一些跟踪活动堆栈的静态(类)变量。如果有任何东西想知道当前的活动是什么,它只需调用BaseActivity 中的一个静态方法,该方法返回我们私有管理堆栈顶部的活动。

        这有点 hacky,但它确实有效。不过我不确定我会推荐它。

        【讨论】:

          【解决方案9】:

          在您想要执行这些方法的类中处理 Intent,并将您的信息以 Bundle 的形式发送给它,如下所示:

              Intent i = new Intent("android.intent.action.MAIN");
              i.setComponent(new ComponentName("com.my.pkg","com.my.pkg.myActivity"));
              Bundle data = new Bundle();
          
              i.putExtras(data);
          
              startActivityForResult(i);
          

          然后使用 OnActivityResultListener 获取新数据。

          【讨论】:

          • 不,这不是我要找的。我想要的只是对当前活动或主要活动的引用。您可以让一个类调用一个类并深入研究。不需要将上下文传递给每个类。
          【解决方案10】:

          我通过使单例类具有以下类的实例作为成员来解决此问题。

          public class InterActivityReferrer <T> {
              HashMap<Integer, T> map;
              ArrayList<Integer> reserve;
          
              public InterActivityReferrer() {
                  map = new HashMap<>();
                  reserve = new ArrayList<>();
              }
          
              public synchronized int attach(T obj) {
                  int id;
                  if (reserve.isEmpty()) {
                      id = reserve.size();
                  }
                  else {
                      id = reserve.remove(reserve.size() - 1);
                  }
          
                  map.put(id, obj);
                  return id;
              }
          
              public synchronized T get(int id) {
                  return map.get(id);
              }
          
              public synchronized T detach(int id) {
                  T obj = map.remove(id);
                  if (obj != null) reserve.add(id);
                  return obj;
              }
          }
          

          这个类可以获取一个 T 对象并返回一个由 attach() 分配给该对象的唯一整数。除非 HashMap 失败,否则分配的整数不会相互冲突。每个分配的整数将在其对应的对象被 detach() 分离时被释放。当附加一个新对象时,释放的整数将被重用。

          并且来自单例类:

          public class SomeSingleton {
              ...
              private InterActivityReferrer<Activity> referrer = new InterActivityReferrer<>();
              ...
              public InterActivityReferrer<Activity> getReferrer() {return referrer;}
          }
          

          并且来自需要参考的活动:

              ...
              int activityID = SomeSingleton.getInstance().getReferrer().attach(this);
              ...
          

          现在,与此活动实例对应的唯一整数被返回。并且可以使用 Intent 和 putExtra() 将整数传递到另一个启动活动中。

              ...
              Intent i = new Intent(this, AnotherActivity.class);
              i.putExtra("thisActivityID", activityID);
              startActivityForResult(i, SOME_INTEGER);
              ...
          

          从另一个活动:

              ...
              id refereeID = getIntent().getIntExtra("thisActivityID", -1);
              Activity referredActivity = SomeSingleton.getInstance().getReferrer().get(refereeID);
              ...
          

          最后可以参考活动。并且 InterActivityReferrer 可以用于任何其他类。

          我希望这会有所帮助。

          【讨论】:

            【解决方案11】:
            public static Activity getLaunchActivity()
            {
                final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            
                final Method methodApp = activityThreadClass.getMethod("currentApplication");
                App = (Application) methodApp.invoke(null, (Object[]) null);
                Intent launcherIntent = App.getPackageManager().getLaunchIntentForPackage(App.getPackageName());
                launchActivityInfo = launcherIntent.resolveActivityInfo(App.getPackageManager(), 0);
                Class<?> clazz;
                try
                {
                    clazz = Class.forName(launchActivityInfo.name);
                    if(clazz != null)
                        return Activity.class.cast(clazz.newInstance());
                }
                catch (Exception e)
                {}
            
                return null;
            }
            

            【讨论】:

            • 请添加一些您的代码在做什么的解释。
            【解决方案12】:

            只是一个猜测,因为我还没有这样做,但它可能会起作用。

            1) 通过将您的 Android 应用程序类设为 Singleton 来获取您的 applicationContext。

            2) 从上下文中获取您的 ActivityManager 类。

            3) 使用 ActivityManager 上的 getRunningTasks() 获取 RunningTaskInfos 列表。

            4) 从列表中获取第一个 RunningTaskInfo 元素,该元素应该是最近启动的任务。

            5) 在该 RunningTaskInfo 上调用 topActivity,它应该为您返回该任务的活动堆栈上的顶部活动。

            现在,这似乎比这里提到的任何其他方法都要多做很多工作,但是您可以将它封装在一个静态类中,然后随时调用它。似乎它可能是在不添加对活动的引用的情况下获得堆栈顶部活动的唯一方法。

            【讨论】:

            • 我没有给你投反对票,但是......这种技术的一个问题是你需要获得 getRunningTasks() 的权限,这会吓到很多用户。
            • @DavidWasser 是的,我不推荐这种方法,但我发布了更多内容,以展示您需要完成什么样的工作才能在没有参考。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-05-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多