理由と解決策は次のとおりです: 1. 静的内部クラスを使用して、スレッドによるメモリ リークを回避します。 2. キャッシュされた ConvertView を使用してアダプタを構築し、ListView によるメモリ リークを回避します。 3. プログラムを終了する前に、コレクションコンテナーでのメモリリークを避けるために、コレクション内の内容は null に設定されます。
# このチュートリアルの動作環境: Windows 7 システム、Dell G3 コンピューター。
1. シングルトンによるメモリ リーク
シングルトンによる静的インスタンスの性質により、そのライフ サイクルはアプリケーションのライフ サイクルと同じ長さになります。オブジェクトが不要になり、シングルトン オブジェクトがまだオブジェクトへの参照を保持している場合、オブジェクトは正常にリサイクルできず、メモリ リークが発生します。 。 例: シングルトンによって引き起こされるメモリ リークのインスタンスを防止する// 使用了单例模式 public class AppManager { private static AppManager instance; private Context context; private AppManager(Context context) { this.context = context; } public static AppManager getInstance(Context context) { if (instance != null) { instance = new AppManager(context); } return instance; } }
2. 静的インスタンスを作成する非静的内部クラスによって引き起こされるメモリ リーク
Forたとえば、頻繁に開始されるアクティビティでは、同じデータ リソースの繰り返し作成を避けるために、次のような記述が表示される場合があります:public class MainActivity extends AppCompatActivity { private static TestResource mResource = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(mResource == null){ mResource = new TestResource(); } //... } class TestResource { //... } }
3. Handler によるメモリ リーク
例: 匿名内部クラスの静的オブジェクトを作成しますpublic class MainActivity extends AppCompatActivity { private final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // ... } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new Runnable() { @Override public void run() { // ... handler.sendEmptyMessage(0x123); } }); } }
4. スレッドによるメモリ リーク
例: AsyncTask と Runnablepublic class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Thread(new MyRunnable()).start(); new MyAsyncTask(this).execute(); } class MyAsyncTask extends AsyncTask<Void, Void, Void> { // ... public MyAsyncTask(Context context) { // ... } @Override protected Void doInBackground(Void... params) { // ... return null; } @Override protected void onPostExecute(Void aVoid) { // ... } } class MyRunnable implements Runnable { @Override public void run() { // ... } } }
5. リソースを閉じないことによるメモリ リーク
BroadcastReceiver、ContentObserver、File、Cursor、Stream、Bitmap などのリソースについては、破棄する必要があります。アクティビティが破棄されるまでに、閉じるかログアウトしてください。そうしないと、これらのリソースがリサイクルされず、メモリ リークが発生します。 1) たとえば、BraodcastReceiver はアクティビティに登録されていますが、アクティビティの終了後も BraodcastReceiver の登録は解除されません。 2) カーソル、ストリーム、ファイルなどのリソース オブジェクトは、バッファを使用することがよくあります。これらを使用していないときは、バッファがメモリを適時に再利用できるように、適時にそれらを閉じる必要があります。それらのバッファは Java 仮想マシン内に存在するだけでなく、Java 仮想マシンの外部にも存在します。参照を閉じずに単に null に設定すると、メモリ リークが頻繁に発生します。 3) リソース オブジェクトが使用されていない場合は、close() 関数を呼び出してオブジェクトを閉じ、null に設定する必要があります。プログラムの終了時にリソース オブジェクトが閉じられていることを確認する必要があります。 4) Bitmap オブジェクトが使用されなくなったら、recycle() を呼び出してメモリを解放します。 2.3 以降のビットマップは、メモリがすでに Java 層にあるため、手動でリサイクルする必要はありません。6. ListView 使用時に発生するメモリ リーク
最初に、ListView は現在の画面レイアウトに従って BaseAdapter から一定数の View オブジェクトをインスタンス化し、ListView はこれらをキャッシュします。オブジェクトを表示します。 ListView を上にスクロールすると、最初に一番上にあった項目の View オブジェクトがリサイクルされ、下に表示される項目の構築に使用されます。この構築プロセスは getView() メソッドによって完了します。getView() の 2 番目の仮パラメータ ConvertView は、キャッシュされた項目の View オブジェクトです (初期化中にキャッシュに View オブジェクトがない場合、convertView は null です)。 アダプターを構築するとき、キャッシュされた ConvertView は使用されません。 解決策: アダプターを構築するときに、キャッシュされた ConvertView を使用します。7. コレクションコンテナーでのメモリリーク
通常、いくつかのオブジェクト参照をコレクション コンテナ (ArrayList など) に追加しますが、オブジェクトが必要なくなっても、その参照をコレクションから削除しないため、コレクションはますます大きくなります。このコレクションが静的である場合、状況はさらに深刻になります。
解決策: プログラムを終了する前に、コレクション内の項目をクリアし、null に設定してからプログラムを終了します。
8. WebView によるリーク
WebView オブジェクトを使用しない場合は、その destroy() 関数を呼び出してオブジェクトを破棄し、占有しているメモリを解放する必要があります。そうしないと、長期間占有されていたメモリを再利用できず、メモリ リークが発生します。
解決策: WebView の別のプロセスを開き、AIDL を介してメイン スレッドと通信します。WebView が配置されているプロセスは、ビジネス ニーズに応じて適切な時間を選択して破棄できるため、完全なメモリ解放が実現します。
コンピュータ関連の知識について詳しくは、FAQ 列をご覧ください。
以上がメモリリークの原因と解決策は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。