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 分支关闭,因为你必须修改你的代码

finally {
            istream.close();            
        }

不好 :)

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

更好的 :)

于 2012-09-12T13:26:34.110 回答
0

在大多数情况下,我在 Android 中发生内存泄漏,它来自线程问题。所以,我可以先问你,你是如何调用这个类的(Dlxml,从 AsyncTask 扩展而来)。确保您没有使用匿名变量,例如“new Dlxml().execute()”,因为 Android 的垃圾收集器可能需要很长时间才能检测到线程不再有用(如果您在列表,它会产生很多泄漏)。我想建议您在实现并行处理之前检查这两点:

  • 始终使用静态变量来实例化加载器。这有助于防止泄漏,甚至是 Android 警告注释。尝试在线程和处理程序问题上使用静态类变量;
  • 注意您正在调用哪个线程来更改视图的方法。如果你在一个非主线程中调用一个方法并且改变了视图,logcat 会抛出一个关于泄漏的消息。为此,利用activity的runonuithread方法;

重要的事情:我发现你已经使用了 AsyncTask,并且只在后台做很多事情。这些事情是否会改变观点?您可以在 doInBackground 上进行下载并在onPostExecute更改视图。

您也可以对这些链接感兴趣:

于 2012-09-12T13:50:10.900 回答