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

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


当前回答

科特林

open class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        mInstance = this
    }

    companion object {
        lateinit var mInstance: MyApp
        fun getContext(): Context? {
            return mInstance.applicationContext
        }
    }
}

然后得到Context

MyApp.mInstance

or

MyApp.getContext()

其他回答

下面是一种从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的解决方案仍然更好。

另一种获得上下文而不子类化Application对象和不使用隐藏类的方法是使用ContentProvider。一旦onCreate方法被调用,上下文应该是可用的。您可以在Kotlin中执行类似的操作

class ContextContentProvider : ContentProvider() {
    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?) = 0

    override fun getType(uri: Uri): String? = null

    override fun insert(uri: Uri, values: ContentValues?): Uri? = null

    override fun onCreate(): Boolean {
        applicationContext = context
        return true
    }

    override fun query(
        uri: Uri, projection: Array<String>?, selection: String?,
        selectionArgs: Array<String>?, sortOrder: String?
    ): Cursor? = null

    override fun update(
        uri: Uri, values: ContentValues?, selection: String?,
        selectionArgs: Array<String>?
    ) = 0

    companion object {
        private var applicationContext: Context? = null

        @JvmStatic
        fun applicationContext() = applicationContext
    }
}

在任何需要上下文的地方,都可以调用ContextContentProvider.applicationContext()方法

如果你已经有了另一个内容提供程序,并且没有导出该内容提供程序,请确保在AndroidManifest.xml中使用不同的权限。

<application>
    <provider
        android:name=".ContextContentProvider"
        android:authorities="${applicationId}.ContextContentProvider"
        android:enabled="true"
        android:exported="false" />
</application>

如果你不想修改清单文件,你可以手动将上下文存储在初始活动的静态变量中:

public class App {
    private static Context context;

    public static void setContext(Context cntxt) {
        context = cntxt;
    }

    public static Context getContext() {
        return context;
    }
}

当你的activity(或多个activity)开始时,只需设置上下文:

// MainActivity

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set Context
    App.setContext(getApplicationContext());

    // Other stuff
}

注意:与所有其他答案一样,这是一个潜在的内存泄漏。

我认为你需要一个getAppContext()方法的主体:

public static Context getAppContext()
   return MyApplication.context; 

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