Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
480 views
in Technique[技术] by (71.8m points)

java - "Warning: Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)"

Similar question have been asked here, here and here but the context is quite different from this and moreover the code that gave from this error is written by the makers of Android and Android Studio.

This is the code:

public class MySingleton {
    private static MySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;

    private MySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();

        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
        });
    }

    public static synchronized MySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }
}

The lines giving the warning are:

private static MySingleton mInstance;
private static Context mCtx;

Now if I remove the static keyword, change public static synchronized MySingleton getInstance(Context... to public synchronized MySingleton getInstance(Context... the error disappers but another problem comes up.

I use MySingleton in RecyclerView. So this line

@Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { ImageLoader imageLoader = MySingleton.getInstance(mContext).getImageLoader();

tells me

Non-static method 'getInstance(android.content.Context)' cannot be refrenced from a static context.

Please anybody knows how to fix this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found the solution to this in the answer to a similar question answered by CommonsWare

I quote

The quoted Lint warning is not complaining about creating singletons. It is complaining about creating singletons holding a reference to an arbitrary Context, as that could be something like an Activity. Hopefully, by changing mContext = context to mContext = context.getApplicationContext(), you will get rid of that warning (though it is possible that this still breaks Instant Run — I cannot really comment on that).

Creating singletons is fine, so long as you do so very carefully, to avoid memory leaks (e.g., holding an indefinite static reference to an Activity).

So Google is not actually contracting itself. To fix this, if this.getApplicationContext is supplied as a parameter for the context, then there will be no memory leak.

So in essence, ignore the warning and supply this.getApplicationContext as a parameter for the context.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...