3

編集: xml を解析するためのコードに論理エラーがあると思うので、適切に記述されていればリークは発生しないはずです。

そのため、簡単なテストのために少し前に書いた AsyncTask クラスをプロジェクトに追加しましたが、メモリ リーク エラーが発生しています。

外すと漏れの問題がなくなるので、責任があると確信しています。

これがヒープダンプファイルです(変換済み)http://www7.zippyshare.com/v/83628026/file.html

package com.example.xmldl;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.os.AsyncTask;
import android.util.Xml;

public class Dlxml extends AsyncTask<String, Void, Void> {
    //adding or removing Override didnt matter just to let you know
    InputStream istream = null;
    protected Void doInBackground(String... url){

        try {
            downloadXml(url[0]);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    private void downloadXml(String url) throws IOException {   
        try {
            URL mUrl = new URL(url);
            HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection();
            istream = urlConnection.getInputStream();           
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(istream, null);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "resources");
            while (parser.next() != XmlPullParser.END_TAG) {
                if (parser.getEventType() == XmlPullParser.TEXT) {                  
                    parser.nextTag();                   
                }
                if (parser.getEventType() != XmlPullParser.START_TAG) {
                    continue;
                }               
            }           
        } catch (MalformedURLException e) {
            e.printStackTrace();        
        } catch (XmlPullParserException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            istream.close();            
        }

    }

}
4

3 に答える 3

0

入力ストリームを閉じているとは思わない:

private void downloadXml(String url) throws IOException {   
    try {
        URL mUrl = new URL(url);
        HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection();
        InputStream istream = urlConnection.getInputStream();           
        XmlPullParser parser = Xml.newPullParser();
        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
        parser.setInput(istream, null);
        parser.nextTag();
        parser.require(XmlPullParser.START_TAG, null, "resources");
        while (parser.next() != XmlPullParser.END_TAG) {
            if (parser.getEventType() == XmlPullParser.TEXT) {                  
                parser.nextTag();                   
            }
            if (parser.getEventType() != XmlPullParser.START_TAG) {
                continue;
            }               
        }  
        // dont forget to close the input stream!
        istream.close();
    } catch (IOException e) {
        //error closing istream
        e.printStackTrace();        
    } catch (MalformedURLException e) {
        e.printStackTrace();        
    } catch (XmlPullParserException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally {

    }

}
于 2012-09-12T13:25:02.363 に答える
0

このコードでは、メモリ リークの問題が発生する可能性はありません。したがって、これから含まれるコードに含まれている必要があります。XmlPullParser がわからないので、そこにあるかもしれません。とにかく、入力ストリームは最終分岐で閉じる必要があります。そのためには、コードを変更する必要があります

finally {
            istream.close();            
        }

良くない :)

finally {
      if(istream != null){
            istream.close();            
       }
}

より良い :)

于 2012-09-12T13:26:34.110 に答える
0

Androidでメモリリークが発生するほとんどの場合、それはスレッドの問題が原因です。そこで、まず、このクラス (AsyncTask から拡張された Dlxml) をどのように呼び出しているのかお尋ねします。「new Dlxml().execute()」などの匿名変数を使用していないことを確認してください。これは、Android のガベージ コレクターがスレッドが役に立たなくなったことを検出するのに長い時間がかかる可能性があるためです (リスト、それは多くのリークを生成する可能性があります)。並列処理を実装する前に、次の 2 点を確認することをお勧めします。

  • ローダーをインスタンス化するには、常に静的変数を使用してください。これはリークを防ぐのに役立ち、Android の警告アノテーションですらあります。スレッドとハンドラーの問題で静的クラス変数を使用してみてください。
  • ビューを変更するメソッドを呼び出すスレッドに注意してください。メインではないスレッド内でビューを変更するメソッドを呼び出すと、logcat はリークに関するメッセージをスローします。これには、アクティビティの runonuithread メソッドを利用します。

重要なこと: あなたは AsyncTask を使用しており、多くのことをバックグラウンドでのみ行っていることがわかりました。これらのことの何かがビューを変更しますか? doInBackground でダウンロードを行い、onPostExecuteでビューを変更できます

これらのリンクにも興味があります。

于 2012-09-12T13:50:10.900 に答える