是否有一种方法来获得静态方法内的当前上下文实例?

我正在寻找这种方式,因为我讨厌保存'Context'实例每次它改变。


当前回答

不,我想没有。不幸的是,您只能从Activity或Context的其他子类调用getApplicationContext()。而且,这个问题有点相关。

其他回答

不,我想没有。不幸的是,您只能从Activity或Context的其他子类调用getApplicationContext()。而且,这个问题有点相关。

芬兰湾的科特林:

清单:

<application android:name="MyApplication">

</application>

MyApplication.kt

class MyApplication: Application() {

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    companion object {
        lateinit var instance: MyApplication
            private set
    }
}

然后,您可以通过MyApplication.instance访问该属性

在Kotlin中,将Context/App Context放在同伴对象中仍然会产生警告,不要将Android Context类放在静态字段中;这是一个内存泄漏(也破坏了即时运行)

或者如果你使用这样的东西:

    companion object {
        lateinit var instance: MyApp
    }

这只是愚弄lint不发现内存泄漏,App实例仍然可以产生内存泄漏,因为Application类及其后代是一个Context。

或者,你可以使用功能界面或功能属性来帮助你获得应用上下文。

简单地创建一个对象类:

object CoreHelper {
    lateinit var contextGetter: () -> Context
}

或者你可以使用nullable type更安全:

object CoreHelper {
    var contextGetter: (() -> Context)? = null
}

在你的App类中添加这一行:


class MyApp: Application() {

    override fun onCreate() {
        super.onCreate()
        CoreHelper.contextGetter = {
            this
        }
    }
}

在你的manifest中声明应用名。MyApp


    <application
            android:name=".MyApp"

当你想获取上下文时,只需调用:

CoreHelper.contextGetter()

// or if you use the nullable version
CoreHelper.contextGetter?.invoke()

希望能有所帮助。

下面是一种从UI线程中的任何地方获取应用程序(它是一个上下文)的未记录的方法。它依赖于隐藏的静态方法ActivityThread.currentApplication()。它至少可以在Android 4.x上运行。

try {
    final Class<?> activityThreadClass =
            Class.forName("android.app.ActivityThread");
    final Method method = activityThreadClass.getMethod("currentApplication");
    return (Application) method.invoke(null, (Object[]) null);
} catch (final ClassNotFoundException e) {
    // handle exception
} catch (final NoSuchMethodException e) {
    // handle exception
} catch (final IllegalArgumentException e) {
    // handle exception
} catch (final IllegalAccessException e) {
    // handle exception
} catch (final InvocationTargetException e) {
    // handle exception
}

注意,这个方法有可能返回null,例如,当你在UI线程之外调用这个方法时,或者应用程序没有绑定到线程上。

如果可以更改应用程序代码,使用@RohitGhatol的解决方案仍然更好。

Assuming we're talking about getting the Application Context, I implemented it as suggested by @Rohit Ghatol extending Application. What happened then, it's that there's no guarantee that the context retrieved in such a way will always be non-null. At the time you need it, it's usually because you want to initialize an helper, or get a resource, that you cannot delay in time; handling the null case will not help you. So I understood I was basically fighting against the Android architecture, as stated in the docs

注意:通常不需要子类化Application。在大多数情况下,静态单例可以以更模块化的方式提供相同的功能。如果你的单例需要一个全局上下文(例如注册广播接收器),在调用你的单例的getInstance()方法时,包括context . getapplicationcontext()作为context参数。

并由黛安·哈克伯恩解释

Application作为派生对象存在的唯一原因是,在1.0之前的开发过程中,我们的一个应用程序开发人员不断地纠缠我,说需要一个顶级的应用程序对象来派生,这样他们就可以有一个更“正常”的应用程序模型,我最终屈服了。 我将永远后悔在这一点上做出了让步。:)

她还提出了这个问题的解决方案:

如果你想要的是一些全局状态,可以在应用程序的不同部分之间共享,请使用单例。[…这就更自然地引出了你应该如何管理这些东西——按需初始化它们。

所以我所做的是摆脱扩展Application,并将上下文直接传递给单例helper的getInstance(),同时在私有构造函数中保存对应用程序上下文的引用:

private static MyHelper instance;
private final Context mContext;    

private MyHelper(@NonNull Context context) {
    mContext = context.getApplicationContext();
}

public static MyHelper getInstance(@NonNull Context context) {
    synchronized(MyHelper.class) {
        if (instance == null) {
            instance = new MyHelper(context);
        }
        return instance;
    }
}

调用者将传递一个本地上下文给helper:

Helper.getInstance(myCtx).doSomething();

因此,要正确地回答这个问题:有很多方法可以静态地访问应用程序上下文,但都不建议使用,您应该更喜欢将本地上下文传递给单例的getInstance()。


感兴趣的人可以在fwd博客上阅读更详细的版本