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

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


当前回答

如果你愿意使用RoboGuice,你可以将上下文注入到任何你想要的类中。下面是如何使用RoboGuice 2.0(在撰写本文时是beta 4)的一个小示例

import android.content.Context;
import android.os.Build;
import roboguice.inject.ContextSingleton;

import javax.inject.Inject;

@ContextSingleton
public class DataManager {
    @Inject
    public DataManager(Context context) {
            Properties properties = new Properties();
            properties.load(context.getResources().getAssets().open("data.properties"));
        } catch (IOException e) {
        }
    }
}

其他回答

这样做:

在Android Manifest文件中,声明以下内容。

<application android:name="com.xyz.MyApplication">

</application>

然后编写类:

public class MyApplication extends Application {

    private static Context context;

    public void onCreate() {
        super.onCreate();
        MyApplication.context = getApplicationContext();
    }

    public static Context getAppContext() {
        return MyApplication.context;
    }
}

现在在任何地方都调用MyApplication.getAppContext()来静态地获取应用程序上下文。

另一种获得上下文而不子类化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>

如果你出于某种原因想在任何类中都有Application上下文,而不仅仅是那些扩展应用程序/活动,也许是一些工厂类或帮助类。你可以将以下单例添加到你的应用程序中。

public class GlobalAppContextSingleton {
    private static GlobalAppContextSingleton mInstance;
    private Context context;

    public static GlobalAppContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized GlobalAppContextSingleton getSync() {
        if (mInstance == null) mInstance = 
                new GlobalAppContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }
}

然后在应用程序类的onCreate with中初始化它

GlobalAppContextSingleton.getInstance().initialize(this);

在任何地方通过调用使用它

GlobalAppContextSingleton.getInstance().getApplicationContext()

但是,除了应用程序上下文之外,我不推荐使用这种方法。因为它会导致内存泄漏。

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

我曾经用过这个:

ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();

这是一个有效的上下文,我用来获得系统服务和工作。

但是,我只在框架/基础修改中使用它,并没有在Android应用程序中尝试它。

你必须知道的一个警告:当用这个上下文注册广播接收器时,它将不起作用,你将得到:

java.lang.SecurityException:给定的调用程序包android没有在进程ProcessRecord中运行