2017-04-18 71 views
-1

我最近使用Volley庫作爲單例模式實現。我提到this實現谷歌的開發人員培訓頁:Android上下文泄漏VolleyInstance

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

}

如果有人實例上述單作爲

RequestQueue queue = MySingleton.getInstance(this). getRequestQueue();

它仍然會導致mCtx泄漏,因爲它是聲明爲靜態。

難道他們不應該只是改變辛格爾頓來實現:

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.getApplicationContext()); // <--Already using application 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); 
    } 
    return mRequestQueue; 
} 

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

public ImageLoader getImageLoader() { 
    return mImageLoader; 
} 

}

在這裏,我已經改變mInstance = new MySingleton(context);mInstance = new MySingleton(context.getApplicationContext());

我的問題是:爲什麼它留給用戶發送應用程序上下文?爲什麼不保護這個班級?有什麼想法嗎?

+0

在開發者網站上的實現一切都很好,你唯一需要做的就是始終發送應用程序上下文,而不是活動上下文。 –

+0

這就是要點。爲什麼讓用戶發送應用程序上下文?爲什麼不保護這個班級? –

+0

如果您將應用程序上下文用作靜態,則不會發生內存泄漏,因爲應用程序上下文通過應用程序存在。 –

回答

0

重要的是使用應用程序上下文來創建它:

RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()). 
getRequestQueue(); 

因爲應用程序上下文中的應用程序生命週期它不能導致內存泄漏的existsthe全部時間。

+0

這就是我所指的。爲什麼讓用戶發送應用程序上下文?爲什麼不在這個類中保護並始終使用應用程序上下文? –

0

那麼你可以使用應用上下文但除此之外,沒有什麼太大的事,記得Context的應用程序正在運行,只要存在。所以你真的不能泄露語境。你可以嘗試在你的應用程序從ApplicationController獲取上下文,但它仍然是完全一樣的關於語境:

private MySingleton() { 
    mCtx = ApplicationController.getContext(); 
    mRequestQueue = getRequestQueue(); 
    ... 

,並在您應用class定義getContext()這樣的:

public class ApplicationController extends Application { 

    public static Context getContext(){ 
     return mContext; 
    } 

    ...