从非活动单例类获取应用程序上下文

44
在我的安卓项目中,我有一个ImageAdapter类,在其中为了一些进一步的需要传递应用上下文。
public class ImageAdapter extends BaseAdapter {
    private Context c;

    public ImageAdapter(Context c) {
            this.c = c;
    }
    ...
}
问题是我想把ImageAdapter作为一个单例,以便从我的所有活动中轻松访问此类的实例。但我不知道如何将一个活动中的getApplicationContext()方法的应用程序上下文传递到ImageAdapter中。所以是否有任何“魔法”可以做到这一点?
public class ImageAdapter extends BaseAdapter {

    private Context c;

    private static class Holder {
            public static final ImageAdapter IA = new ImageAdapter();
    }

    private ImageAdapter() {
            this.c = /* some magic here */.getApplicationContext();
    }

    public static ImageAdapter getInstance() {
            return Holder.IA;
    }
    ...
}

也许您对在我的任何活动中共享ImageAdapter有其他想法。 我是Android的新手,对于在活动之间传递数据的方法感到有些困惑。

我将非常感激任何帮助。


1
你在问题中提到:“我想将ImageAdapter作为单例,以便从所有我的活动中轻松访问此类的实例。”如何轻松访问ImageAdapter类的实例并在所有活动中使用,请详细说明,我想增加我的知识。 - blackHawk
3个回答

95

更新:06-Mar-18

使用MyApplication实例而不是Context实例。Application实例本身就是一个单例上下文实例。

public class MyApplication extends Application {

    private static MyApplication mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }

    public static MyApplication getContext() {
        return mContext;
    }
}

之前的回答

你可以通过以下方式获取应用程序上下文:

public class MyApplication extends Application {

    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
    }

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

然后,您可以从方法MyApplication.getContext()调用应用程序上下文。

不要忘记在清单文件中声明应用程序:

<application
    android:name=".MyApplication"
    android:icon="@drawable/icon"
    android:label="@string/app_name" >

5
顺便说一句,应用程序上下文就是应用程序本身;getApplicationContext() 可以替换为 this。(getApplicationContext 的存在是为了让你在任何上下文中获取应用程序。)代码没有问题,只是指出这一点。 - ToolmakerSteve
8
将Android的上下文类放在静态字段中是不可取的。静态字段会泄漏上下文,而且Android Studio也会警告这个问题。 - netpork
6
这个答案还是否有效?因为编译器显示“不要将Android上下文类放在静态字段中;这会导致内存泄漏(并且还会破坏即时运行)。” - Jim Clermonts
3
@JimClermonts,我知道自从您提出问题以来,答案已经更新了,但更新后的答案不应该给出任何警告。区别在于“Context”可以是任何上下文,包括活动(这些活动现在已被销毁),通过指定它是“Application”对象(该对象可伴随整个应用程序生命周期存在),就不应该出现任何问题。 - Anigif
这还有效吗? - Peter

7
我更愿意将上下文实例作为参数传递给单例中真正需要它的每个方法。

1
没有办法,在重写的方法中我需要上下文。 @Override public View getView(int position, View convertView, ViewGroup parent) 据我所知,它会自动触发。 - Dmitry

3

方法一:

由于您指定了ImageAdapter是单例模式,一个简单的解决方案是从具有访问应用程序上下文的类中创建该单例:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        ImageAdapter.createIt(this);
    }
}

public class ImageAdapter extends BaseAdapter {
    private static ImageAdapter it;
    // Get the singleton.
    public static ImageAdapter getIt() {
        return it;
    }
    // Call this once, to create the singleton.
    public static void createIt(Context context) {
        it = new ImageAdapter(context);
    }

    private final Context c;
    private ImageAdapter(Context context) {
        c = context;
    }
}

方法二:

如果它不是单例模式,那么我会使用已接受的答案。在这种情况下,从ImageAdapter中删除局部变量,因为可以始终从MyApplication获取上下文。扩展已接受的答案,如果您想要一个本地方法作为便利,定义ImageAdapter.getContext()。完整解决方案:

public class MyApplication extends Application {
    private static Context appContext;
    public static Context getContext() {
        return appContext;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        appContext = this;
    }
}

public class ImageAdapter extends BaseAdapter {
    public ImageAdapter() {
    }

    // [Optional] Call this whenever you want the app context.
    private Context getContext() {
        return MyApplication.getContext();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接