Androidはどのように最も優れてActivityの中で資源を釈放することを開発します

7206 ワード

前言
現在、Androidの開発に入門し、深い問題に注目し始めています.Androidの開発段階でよく遭遇する問題に直面します.それはメモリの漏れです.実はAndroidのメモリ漏れの多くはactivityのリソースの解放が正しくないため、activityと単例やインタフェースが互いに持っていて解放できない.このブログでは、Androidで最も優れたリソースの解放方法について説明します.
 
エラー解放リソースのいくつかの例
正面の例を見る前に、反対の例を見て、なぜメモリが漏れるのかを理解します.
ActivityのonDestroy()のライフサイクルでリソースを解放
次のonDestroy()メソッドにはmHttpListというリソースが解放されます.activityのライフサイクルの最後がonDestroyメソッドであることはよく知られていますが、なぜonDestroy()でリソースを解放するのに問題があるのでしょうか.
問題はonDestroy()のライフサイクルがすぐに実行されるわけではないことです.Activityはフロントを脱退した後、まずスタックに入った.onDestroy()を実行するかどうかはシステムに任せるが、一般的にはシステムがタイムリーにonDestroy()メソッドを実行してactivityを破棄することは確かであるが、一部のActivityのジャンプが頻繁な場合、システムはすぐにonDestroy()メソッドを実行しない可能性がある.この時点で問題が発生しました.終了すべきリソースがすぐに終了していないと、コールバックエラーやメモリの漏洩が発生する可能性があります.
  @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mHttpList != null){
            mHttpList.release();
            mHttpList = null;
        }
        
    }

Activityのfinish()メソッドでリソースを解放する
環境と同じように、finishメソッドでリソースを解放するにはどのような問題がありますか?
書き換えたfinish()はリソースを解放する良い場所であり、戻るキー(またはonBackPressed()メソッドを自分でアクティブに呼び出す)とfinish()メソッドをアクティブに呼び出すと、書き換えたfinish()は実行されます.しかし、この方法は、バックグラウンドが長すぎると自動的にクリーンアップされるか、他のActivityの起動モードがandroid:launchMode="singleTask"であるか、他のactivityのsingleTaskではスタックの前が自動的にクリーンアップされるので、Activityは、この場合、activityがクリーンアップされるfinish()方法は実行されません.これであなたの資源は解放されません.
    @Override
    public void finish() {
        super.finish();
        if (mHttpList != null){
            mHttpList.release();
            mHttpList = null;
        }
    }

ActivityのonPause()とonStop()でリソースを解放
onPause()とonStop()ではactivityバックグラウンドが知られているときにこの2つのライフサイクルを呼び出してonPause()を呼び出し、onStop()でDialogモードのActivityポップアップであればonPause()にのみ入る.彼らの問題は何ですか.
問題は、操作が速すぎる前にバックグラウンドを操作すると、onRestart()またはonResume()でリソースを頻繁に再初期化または登録する必要があることです.これは、リソースを解放する方法として一般的に推奨されていますが、高速で頻繁な操作の初期化と解放は、メモリの漏洩が最も発生しやすいものです.特に初期化に時間がかかる場合は...
@Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e(TAG, "onStop: ");
    }

Activityでリソースを解放する方法をお勧めします
onPause()またはonStop()はonDestroy()と結合し、isFinishing()を呼び出してメソッドの判断後にリソースを解放します.次のコードがあります.
 
    private boolean mIsRelease = false;

    /**
     *     
     */
    private void release(){
        if (mIsRelease){
            return;
        }
        if (isFinishing()) {
            if (mHttpList != null) {
                mHttpList.release();
                mHttpList = null;
            }
        }
        mIsRelease = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        release();
    }

    @Override
    protected void onStop() {
        super.onStop();
        //          onStop        

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        release();
    }

 
 
注意:空判定を追加するか、またはメソッドにグローバルブール値をセットして、リソースを解放したかどうかを判断し、リソースの再解放を防止することもできます.ここではなぜonDestroy()がもう一度実行されるのですか?以下、原因を説明する.
 
まずisFinishing()の役割は、このactivityが破棄される必要があるか、それともバックグラウンドに入る必要があるかを判断することです.次のことを確認しました.
1.finish()メソッドをアクティブに呼び出す場合、isFinishing()はtrueを返します.
2.onBackPressed()メソッドをアクティブに呼び出す場合、または戻るキーを押す場合、isFinishing()はtrueを返します.
3.他のActivityに入るだけでバックグラウンドに退く場合、isFinishing()はfalseを返します
しかし、isFinishing()は完璧ではなく、もう一つのケースではクリーンアップをスキップすることができる.それはSingleTaskモードではこのActivityが破棄されるが、バックグラウンドではインスタック(インシンクが少なくとも3階にある場合)がonPauseまたはonStopをトリガーしているため、SingleTaskのクリーンアップはisFinishing()の判断をスキップし、そのままonDestroy()に着いた.
だから、私たちはonDestroy()で再び底をついて、SingleTaskの原因で資源を解放しないことを保証する必要があります.
 
最後に、以上のような解放資源の組み合わせは、Activityが本当に廃棄される時にできるだけ早く資源を解放することを目的とし、Activityがバックグラウンドで資源を繰り返し登録する必要があるだけであることを防止し、最後にonDestroy()のポケットに頼って資源がSingleTaskの原因で解放されないことを保証することを目的としている.
 
Fragmentでのリソースの解放
Activityが削除されたかどうかを判断する方法もあります
final public boolean isRemoving() {
        return mRemoving;
    }

 
 
End