Androidメモリの流出のいくつかの可能性をまとめた


Javaはゴミ回収言語の一種で、開発者がメモリ割り当てを特に管理する必要がなく、アプリケーションが局部的な障害によって崩壊し、同時に未釈放のメモリがスタックを押しつぶす可能性があるので、書いたコードはより安全であるという利点があります。
残念なことに、Javaにはまだたくさん存在しています。メモリの漏洩を招きやすいロジックがあります。もし注意しないならば、あなたのAndroidの応用は釈放していないメモリを浪費しやすくて、最後にメモリが光の誤りを使うことを招きます。
一般的なメモリ漏れの原因は、オブジェクトの参照がすべて解放された場合、オブジェクトはまだリリースされていません。Cursorが閉じるのを忘れるなど)
論理メモリのリークの原因は、アプリケーションがこのオブジェクトを必要としない場合、オブジェクトのすべての参照がまだリリースされていないからです。
対象の強い引用を持っていると、ゴミ回収器はメモリからこの対象を回収できません。
Android開発において、最も誘発しやすいメモリ漏れ問題はContectです。例えばActivityのContectは、大量のメモリ参照、例えばView Herarchiesとその他の資源を含んでいます。一旦Contectが漏れたら、それが指すすべての対象を漏らすことも意味します。Androidマシンのメモリは有限で、多すぎるメモリの漏洩はOOMを招きやすいです。
検出ロジックのメモリ漏れは主観的な判断が必要で、特に対象のライフサイクルははっきりしていない。幸いにも、Activityははっきりしたライフサイクルを持っていて、漏れの原因を発見しやすいです。Activity.onDestroyはActivityの生命の終焉と見なされています。プログラム上では破壊されたはずです。あるいはAndroidシステムはこれらのメモリを回収する必要があります。
この方法が実行され終わったら、スタックの中にこのActivityの強い引用が残っています。ゴミ回収器は回収されたメモリとしてマークできません。本来の目的はそれを回収することです。
その結果、Activityはライフサイクルの外で生きています。
Activityはヘビー級のオブジェクトで、Androidシステムに処理させるべきです。しかし、論理メモリのリークは、いつも予期せぬ間に発生します。Activityを試したことがありますが、20 Mメモリが漏れてしまいました。Androidでは,潜在的メモリの漏えいを引き起こすトラップは2つにすぎない。
1.グローバルプロセスのstatic変数。これはアプリケーションを無視した状態で、Activityの強引用を持つモンスターです。
2.Activityライフサイクル以外に生きるスレッド。Activityに対する強い引用はクリアされていません。
下記の状況に遭遇したかどうか確認してください。
Static Activities
クラスで静的Activity変数を定義し、現在動作しているActivityのインスタンスをこの静的変数に割り当てます。
この静的変数がActivityライフサイクル終了後にクリアされていないと、メモリが漏れます。static変数はこのアプリケーションのライフサイクルを貫いているため、漏れたActivityはアプリケーションの中にずっと存在し、ゴミ回収器に回収されません。

  static Activity activity;

  void setStaticActivity() {
   activity = this;
  }

  View saButton = findViewById(R.id.sa_button);
  saButton.setOnClickListener(new View.OnClickListener() {
   @Override public void onClick(View v) {
    setStaticActivity();
    nextActivity();
   }
  });


Memory Leak 1 C Static Activity
Static View
同様な場合は、一例モードで発生し、Activityが頻繁に使用される場合、メモリに一例を保存するのが実用的である。先にも述べたように、Activityのライフサイクルを強制的に延長するのはかなり危険で、必要ではないので、どうしてもできません。
特別な状況:もし1つのView初期化が大量の資源を消費し、1つのActivityライフサイクル内で不変のままであれば、それをstaticに変えて、ビューツリーにロードすることができます。このようにActivityが破壊された時、資源を放出します。例のコードの中にはメモリを解放していません。このstatic viewをnullにセットすればいいですが、やはりこのstatic viewの方法は勧められません。

  static view;

  void setStaticView() {
   view = findViewById(R.id.sv_button);
  }

  View svButton = findViewById(R.id.sv_button);
  svButton.setOnClickListener(new View.OnClickListener() {
   @Override public void onClick(View v) {
    setStaticView();
    nextActivity();
   }
  });



メモリ2 C Static View
Inner Class
引き続き、Activityには内部クラスがあると仮定し、これにより可読性とパッケージ性を向上させることができる。内部カテゴリを作成して、静的変数の引用を持っています。おめでとうございます。メモリ漏れはあなたから遠くないです。

 private static Object inner;

    void createInnerClass() {
    class InnerClass {
    }
    inner = new InnerClass();
  }

  View icButton = findViewById(R.id.ic_button);
  icButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      createInnerClass();
      nextActivity();
    }
  });


Memory Leak 3 C Innerクラス
内部クラスの利点の一つは外部クラスにアクセスできることです。残念なことに、メモリ漏れの原因は、内部クラスが外部クラスの実例を持っていることです。
Anonymous Class
同様に、匿名クラスも外部クラスの参照を維持している。メモリ漏れが発生しやすいので、Activityで匿名のAyncTskを定義すると
。非同期タスクがバックグラウンドで実行されている間、Activityは不運にも破壊されました。これはAyncTaskに保有されているActivityのインスタンスはごみ箱に回収されません。

 void startAsyncTask() {
    new AsyncTask<Void, Void, Void>() {
      @Override protected Void doInBackground(Void... params) {
        while(true);
      }
    }.execute();
  }

  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  View aicButton = findViewById(R.id.at_button);
  aicButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      startAsyncTask();
      nextActivity();
    }
  });


Memory Leak 4 C AsyncTask
ハードラー
同様に、匿名のRunnableを定義し、匿名のHandlerで実行する。Runnable内部クラスは外部クラスの暗黙的な引用を持ち、HandlerのメッセージキューMessage Queに伝達され、Messageメッセージが処理されていない前にActivityインスタンスが破壊されず、メモリが漏洩してしまう。

 void createHandler() {
    new Handler() {
      @Override public void handleMessage(Message message) {
        super.handleMessage(message);
      }
    }.postDelayed(new Runnable() {
      @Override public void run() {
        while(true);
      }
    }, Long.MAX_VALUE >> 1);
  }

  View hButton = findViewById(R.id.h_button);
  hButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      createHandler();
      nextActivity();
    }
  });


Memory Leak 5 C Handler
Threads
私たちは再びThreadとTimerTaskを通じてメモリ漏れを見せます。

  void spawnThread() {
    new Thread() {
      @Override public void run() {
        while(true);
      }
    }.start();
  }

  View tButton = findViewById(R.id.t_button);
  tButton.setOnClickListener(new View.OnClickListener() {
   @Override public void onClick(View v) {
     spawnThread();
     nextActivity();
   }
  });


メモリ6 C Thread
TimeTask
匿名クラスの例であれば、ワークスレッドであろうとなかろうと、Activityの参照を持ってメモリが漏洩します。

 void scheduleTimer() {
    new Timer().schedule(new TimerTask() {
      @Override
      public void run() {
        while(true);
      }
    }, Long.MAX_VALUE >> 1);
  }

  View ttButton = findViewById(R.id.tt_button);
  ttButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
      scheduleTimer();
      nextActivity();
    }
  });


Memory Leak 7 C TimeTask
Sensor Manager
最後に、Contect.getSystem Serviceを通じてシステムサービスを取得することができます。これらのサービスはそれぞれのプロセスにおいて、バックグラウンドタスクを処理し、ハードウェアインタラクションを処理するのを助けます。これらのサービスを利用すれば、モニターを登録することができます。これはサービスがConttextの引用を持っています。Activityが破壊された時にこれらのモニターをキャンセルしなかったら、メモリが漏れます。

  void registerListener() {
        SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
        sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
    }

    View smButton = findViewById(R.id.sm_button);
    smButton.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        registerListener();
        nextActivity();
      }
    });


メモリ8 C Sensor Manager
締め括りをつける
あれだけ多く見たら、メモリが漏れてしまいます。携帯電話のメモリを全部食べてしまい、ゴミの回収処理が頻繁に行われます。最悪の場合はOOMを招きます。ゴミ回収の作業は高額な出費で、肉眼で見えるカートンを招きます。したがって、実用化の際は引用チェーンを持つことに注意し、メモリ漏洩検査を頻繁に行います。
以上はAndroidメモリに漏れた資料を整理して、引き続き関連資料を補充します。ありがとうございます。