ContextとApplication Context


Androidではcontextは多くの操作ができますが、最も主要な機能はリソースのロードとアクセスです.
androidには2つのcontextがあり、1つはアプリケーションcontextであり、1つはactivity contextであり、通常、各種類と方法の間でactivity contextが伝達されている.
例えばactivityのonCreate:
   
   
   
   
  1. protected void onCreate(Bundle state) { 
  2.  
  3.         super.onCreate(state); 
  4.  
  5.         TextView label =new TextView(this); // context view control 
  6.  
  7.         label.setText("Leaks are bad"); 
  8.  
  9.         setContentView(label); 
  10.  

Activity contextをviewに渡すことは、viewがactivityを指す参照を持っていることを意味し、さらにactivityが占有するリソース:view hierachy、resourceなどを参照することを意味する.
これによりcontextからメモリが漏れると、多くのメモリが漏れる.
ここで漏れたのはgcがactivityのメモリを回収できないという意味です.
画面が回転すると、現在のactivityが破棄され、ステータス情報が保存され、新しいものが作成されます.例えば、大きな画像をロードする必要があるアプリケーションを書きました.スクリーンを回転するたびにこの画像を破棄し、再ロードしたくないです.この要件を達成するための簡単なアイデアは、Activityクラスが作成した破棄が常にメモリに保存されるように、静的Drawableを定義することです.
   
   
   
   
  1. public class myactivity extends Activity { 
  2.  
  3.         private static Drawable sBackground; 
  4.  
  5.         protected void onCreate(Bundle state) { 
  6.  
  7.                 super.onCreate(state); 
  8.  
  9.                 TextView label = new TextView(this); 
  10.  
  11.                 label.setText("Leaks are bad"); 
  12.  
  13.                 if (sBackground == null) { 
  14.  
  15.                         sBackground = getDrawable(R.drawable.large_bitmap); 
  16.  
  17.                 } 
  18.  
  19.         label.setBackgroundDrawable(sBackground);//drawable attached to a view 
  20.  
  21.         setContentView(label); 
  22.  
  23.         } 
  24.  

このプログラムは簡単そうに見えますが、問題が大きいです.スクリーンが回転するとleak(すなわちgcはactivityを破棄できない)があります.
スクリーンが回転すると、現在のactivityが破棄されるとさっき言いました.しかしdrawableがviewに関連付けられるとdrawableはviewのreference、すなわちsBackgroundはlabelの参照を保存し、labelはactivityの参照を保存する.すなわちdrawableは破棄できず、参照されたものも間接的に参照されたものも破棄できないため、現在のactivityを破棄することができず、メモリの漏洩が発生します.gcはこのタイプのメモリ漏洩にはどうしようもない.
このようなメモリ漏洩を回避する方法は、activity内の任意のオブジェクトのライフサイクルがactivityよりも長くなることを回避し、activityへのオブジェクトの参照によってactivityが正常に破棄されないことを回避することです.アプリケーションcontextを使用できます.アプリケーションcontextはアプリケーションの一生を伴い、activityのライフサイクルとは関係ありません.アプリケーションcontextはContext.getApplicationContextまたはActivity.getApplicationメソッド取得.
 
context関連のメモリ漏洩を回避するには、以下の点を覚えておいてください.ライフサイクルの長いオブジェクトにactivity contextを参照させないでください.すなわち、activityを参照するオブジェクトがactivity自体のライフサイクルと同じであることを保証します.ライフサイクルの長いオブジェクトでは、アプリケーションcontext 3を使用できます.非静的な内部クラスを回避し、できるだけ静的クラスを使用し、ライフサイクルの問題を回避し、外部オブジェクトへの内部クラスの参照によるライフサイクルの変化に注意します.