Java,Android記憶體洩漏程式碼片段
阿新 • • 發佈:2019-02-13
一個生命週期長的物件引用了一個生命週期短的物件,導致短物件無法被回收
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * 這裡需要一個回撥物件,當前Activity實現了回撥介面,並將當前Activity的引用傳遞給網路請求模組 * 噹噹前Activity被finish掉,但網路請求模組持有的Activity的引用還未釋放(比如網路處理還未完成或者沒有釋放引用), * 這時就會造成Activity無法被GC回收,造成記憶體洩漏 */ netWorkManager.request(url,this); /** * 傳遞需要介面的物件就不會導致Activity洩漏了 */ netWorkManager.request(url, new NewworkCallBack() { @Override public void onSuccess() { } @Override public void onFail() { } }); } @Override public void onSuccess() { } @Override public void onFail() { } }
與流有關的溢位,比如流沒有被關閉
public class MemoryLeakDemo extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * ref: http://stackoverflow.com/questions/9515465/strictmode-complains-about-inputstream-not-being-closed */ /** * 看BufferedInputStream和FileInputStream的原始碼可知,它們的建構函式裡會報異常,FileInputStream或BufferedInputStream物件會生成, * 但 objectInputStream仍然為null,在finally程式碼塊中就並不會close FileInputStream和BufferedInputStream物件 */ ObjectInputStream objectInputStream; File file; try { file = new File("demo/myfile"); objectInputStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)),STREAM_BUFFER_SIZE); ... } catch (IOException e) { e.printStackTrace(); }finally { closeQuietly(objectInputStream); } /** * 解決辦法很簡單 */ FileInputStream fileInputStream; BufferedInputStream bufferedInputStream; ObjectInputStream objectInputStream; File file; try { file = new File("demo/myfile"); fileInputStream = new FileInputStream(file); bufferedInputStream = new BufferedInputStream(fileInputStream,STREAM_BUFFER_SIZE); objectInputStream = new ObjectInputStream(bufferedInputStream); ... } catch (IOException e) { e.printStackTrace(); }finally { closeQuietly(fileInputStream); closeQuietly(bufferedInputStream); closeQuietly(objectInputStream); } } private void closeQuietly(InputStream is){ if(is != null){ try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } }
與Context有關的溢位。
對於需要Context的長期存在的物件,要使用ApplicataionContext,而不要使用Activity的Context,否則會導致Activity無法被回收。
使用Activity的Context的物件的生命週期要和Activity一致。
不要在Activity內使用內部類,如果無法控制它的生命週期的話,使用靜態內部類替代,並且用WeakReference引用外部的Activity。因為內部類會拿著外部類的引用,所以內部類有可能導致外部類無法被回收。
public class MemoryLeakDemo extends Activity{ private static Drawable sBackground; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * android應用中,對Context的不適當使用會造成Activity的無法被回收 * 比如此例中,large_bitmap是個大圖片,這個Activity可能會啟用多次,為了節省載入圖片的時間,將其設成靜態變數 * 這會提高速度,但會導致Activity無法被回收,因為View會作為Drawable的callback,Drawable拿著View的引用, * View又拿著Activity的引用。 * 解決方法可以是,在Activity退出時將Drawable的callback置為null */ TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground = getDrawable(R.drawable.large_bitmap); } label.setBackgroundDrawable(sBackground); setContentView(label); } }