“警告:不要将Android上下文类放在静态字段中;这是内存泄漏(并且还会中断”即时运行“)”

时间:2016-10-17 19:17:05

标签: java android memory-leaks android-volley

类似的问题一直是asked hereherehere,但背景与此完全不同,此外code that gave from this error由Android和Android Studio制作人撰写

这是代码:

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;
    }
}

发出警告的行是:

private static MySingleton mInstance;
private static Context mCtx;

现在,如果我删除了static关键字,请将public static synchronized MySingleton getInstance(Context...更改为public synchronized MySingleton getInstance(Context...错误消息,但会出现另一个问题。

我在RecyclerView中使用MySingleton。所以这一行

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

告诉我

  

非静态方法'getInstance(android.content.Context)'无法从静态上下文中获取。

请有人知道如何解决这个问题吗?

5 个答案:

答案 0 :(得分:15)

我在answer to a similar question answered by CommonsWare

中找到了解决方法

我引用

  

引用的Lint警告并没有抱怨创建单身人士。   它抱怨创建单身人士持有一个参考   任意上下文,因为它可能类似于Activity。   希望通过将mContext = context更改为mContext =   context.getApplicationContext(),你将摆脱那个警告   (虽然有可能这仍然打破了瞬间跑 - 我不能   真的评论那个。)

     

创建单身人士是好的,只要你非常小心地这样做   避免内存泄漏(例如,保持一个不确定的静态引用   活性)。

因此谷歌实际上并没有签约。要解决这个问题,如果提供this.getApplicationContext作为上下文的参数,那么就不会有内存泄漏。

因此,实质上,忽略警告并提供this.getApplicationContext作为上下文的参数。

答案 1 :(得分:4)

我最终把它放在没有警告的AppController中。

public class AppController extends MultiDexApplication {

    public static Context getContext() {
        return mInstance.getApplicationContext();
    }

    private static AppController mInstance;

    public static synchronized AppController getInstance() {
        return mInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();

        mInstance = this;

    }
}

因此,无论何时需要,只需致电AppController.getContext()

答案 2 :(得分:0)

我只是删除了对上下文的静态引用,并且没有错误:

public class RequestQueueSingleton {

    private RequestQueue requestQueue;
    private final ImageLoader imageLoader;
    private final Context ctx;

    private RequestQueueSingleton(Context context) {
        ctx = context;
        requestQueue = getRequestQueue();

        imageLoader = new ImageLoader(requestQueue,
                new ImageLoader.ImageCache() {
                    private final LruCache<String, Bitmap>
                            cache = new LruCache<>(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 RequestQueueSingleton getInstance(Context context) {
        RequestQueueSingleton instance;
        instance = new RequestQueueSingleton(context);
        return instance;
    }

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

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

    public ImageLoader getImageLoader() {
        return imageLoader;
    }
}

答案 3 :(得分:-1)

这是我的解决方案。当您刚刚返回RequestQueue的实例时,无需保留静态引用?

public class VolleyRequestQueue {

    private static VolleyRequestQueue mInstance;
    private RequestQueue mRequestQueue;

    private VolleyRequestQueue() {

    }

    public static synchronized VolleyRequestQueue getInstance() {
        if(mInstance == null) {
            mInstance = new VolleyRequestQueue();
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue(Context context) {
        if(mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(context.getApplicationContext());
        }
        return mRequestQueue;
    }
}

答案 4 :(得分:-1)

我写了这个单例类,没有发现内存泄漏或其他警告。

using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{ 
  command.CommandText = "UPDATE Student SET Name = @name where id = @id";

  command.Parameters.AddWithValue("@name", name);
  command.Parameters.AddWithValue("@id", myId);

  connection.Open();

  command.ExecuteNonQuery();

  connection.Close();
}