Android:EditText导致内存泄漏

我想先说这是我第一次处理性能,因为这是我第一次开发一个android应用程序。

应用程序

该应用程序是一个源代码编辑器,您可以打开文件,修改它们并将其保存回来。 该应用程序由4个部分组成:

  • 导航器视图:包含打开文件的ListView和打开文件夹的TreeView。
  • 代码视图容器:这包含了包含实际代码的视图。
  • 代码容器:这是一个包含文本视图和自定义EditText(由我扩展EditText类创build,但尚未实现,所以它的行为完全像一个EditText)的小视图。 TextView只是显示代码行。
  • 打开和保存的片段:我使用了2个片段作为DialogFragment:保存片段让您浏览本地文件系统以及链接帐户的Dropbox文件系统并保存当前文件。 打开的片段可让您导航相同的文件系统并打开文件。

问题

在完成基本代码编辑器之后,我转到了语法高亮显示。 现在,我想清楚地知道,即使没有语法高亮,也会产生泄漏,所以这不是问题。

无论如何,通过testing语法highlithing,我打开“大”的文件(1200行代码),我注意到,该应用程序变得极其缓慢,这是显而易见的,因为我regexing整个文本(我将通过突出显示只可见的文字)。 这促使我testing应用程序没有语法highlithing与大文件,我发现应用程序变得有点慢,我注意到一些内存泄漏发生。

特别是,当我打开一个大文件(1200行代码)的应用程序需要1秒钟显示在textview中的代码行,当我input字符的绘图是缓慢的。 另外,无论何时删除一个字符,都会发生内存泄漏。

检验

我试图检查堆(与MAT),但据说我没有任何经验,我不知道该怎么做来调查这个问题。 我很抱歉,但我不能上传截图(没有通过stackoverflow的权限),但我可以报告你一些数字:

系统在打开大文件之前

系统总览

在这里输入图像说明

泄漏嫌疑人

在这里输入图像说明

问题1 在这里输入图像说明

细节: 在这里输入图像说明

问题2 在这里输入图像说明

问题3 在这里输入图像说明

最大的顶级支配者包

在这里输入图像说明在这里输入图像说明

最大的对象

在这里输入图像说明

系统打开大文件后

系统总览

在这里输入图像说明

泄漏嫌疑人:

在这里输入图像说明

问题1在这里输入图像说明 细节: 在这里输入图像说明

问题2在这里输入图像说明

问题3问题4 在这里输入图像说明

最大的顶级支配者包

在这里输入图像说明在这里输入图像说明

最大的对象

在这里输入图像说明

从Android设备监视器:

系统在打开大文件之前

在这里输入图像说明

系统打开大文件后

在这里输入图像说明

分配的一些部分:

在这里输入图像说明在这里输入图像说明在这里输入图像说明 先谢谢你

编辑:

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/codeScrollView" android:fillViewport="true"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="fill_parent" android:background="@drawable/lines_stroke" android:textColor="@android:color/white" android:text="@string/first_line" android:textSize="15dp" android:gravity="right" android:paddingLeft="15dp" android:paddingRight="5dp" android:id="@+id/edit_code_lines_view"/> <com.example.green.bachelorproject.customViews.codeEditView.TouchEditText android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/code_stroke" android:gravity="top" android:textColor="@android:color/white" android:textSize="15dp" android:paddingLeft="3dp" android:paddingRight="3dp" android:textCursorDrawable="@color/white" android:id="@+id/edit_code_content_view"/> </LinearLayout> </ScrollView> 

编辑

好吧,我发现这个问题。 如果您看到每次键入内容时都会更新EditText行,并且由于文本很长(1200行),所以需要一段时间才能重新计算。 虽然关于那个活动了! 我必须find一个更快的方式来显示代码行。 一种select是每行使用一个TextView,这样我只更新需要改变的TextView。 但是我不知道有1200个TextView对象是不是很好。

    包com.example.green.bachelorproject.customViews.codeEditView;

    导入android.content.Context;
     import android.graphics.Color;
    导入android.graphics.Typeface;
     import android.text.Editable;
     import android.text.Spannable;
     import android.text.SpannableStringBuilder;
     import android.text.TextWatcher;
     import android.text.style.ForegroundColorSpan;
    导入android.util.AttributeSet;
    导入android.util.Log;
     import android.view.LayoutInflater;
    导入android.widget.EditText;
    导入android.widget.LinearLayout;
    导入android.widget.TextView;

    importutils.Colorizer;
    importutils.Lexer;
     import com.example.green.bachelorproject.events.UpdateCacheFileEvent;
     import com.example.green.bachelorproject.R;

    导入de.greenrobot.event.EventBus;
     import com.example.green.bachelorproject.internalFileSystem.InternalFile;

     import java.util.ArrayList;

     / **
      *由Green在15/02/15创build。
      * /
    公共类CodeEditView扩展LinearLayout {

        私人上下文环境;
        私人TextView线;
        私人EditText代码;
        私人字体currentTypeface;
        私人InternalFile internalFile;
        私人Lexer词法分析器;
        私人Colorizer着色器;

        公共CodeEditView(上下文上下文){
            超级(上下文);
             this.context = context;
            的init(NULL);
         }   

        公共CodeEditView(上下文上下文,AttributeSet attrs){
             super(context,attrs);
             this.context = context;
            的init(ATTRS);
         }

         private void init(AttributeSet attrs){
             //检查这个
             LayoutInflater layoutInflater =(LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             layoutInflater.inflate(R.layout.edit_code_layout,this);

     // this.colorizer = new Colorizer();
     // this.colorizer.setColor(“String”,Color.rgb(218,220,95));
     // this.colorizer.setColor(“Number”,Color.rgb(173,125,255));
     // this.colorizer.setColor(“Character”,Color.rgb(218,220,95));
     // this.colorizer.setColor(“Operator”,Color.rgb(234,38,116));
     // this.colorizer.setColor(“Keyword”,Color.rgb(234,38,116));
     // this.colorizer.setColor(“Identifier”,Color.WHITE);
     // this.colorizer.setColor(“Type”,Color.rgb(105,216,238));
     // this.colorizer.setColor(“Comment”,Color.rgb(117,113,91));
             this.lexer =新的Lexer();
             this.lines =(TextView)findViewById(R.id.edit_code_lines_view);
             //this.lines.setTypeface(currentTypeface);
             this.code =(EditText)findViewById(R.id.edit_code_content_view);
             //this.code.setTypeface(currentTypeface);
             this.code.addTextChangedListener(new TextWatcher(){



             @覆盖
             public void beforeTextChanged(CharSequence s,int start,int count,int after){
             }

             @覆盖
             public void onTextChanged(CharSequence s,int start,int before,int count){
             }

             @覆盖
             public void afterTextChanged(Editable s){
     // writeToFile();
                 //EventBus.getDefault().post(new UpdateCacheFileEvent(code.getText()。toString(),internalFile));
                 // setLines();
             }
         });
     }

     private void setLines(){
         int usedLines = code.getLineCount();

         String text =“1”+ System.lineSeparator();

         for(int i = 2; i tokens = lexer.tokenize(content);
     // SpannableStringBuilder text = new SpannableStringBuilder(content);
     //
     // for(Lexer.Token t:令牌){
     // text.setSpan(new ForegroundColorSpan(colorizer.getColor(t)),t.start,t.end,Spannable.SPAN_INCLUSIVE_INCLUSIVE);
     //}

     // code.setText(text);
     // code.post(new Runnable(){
     // @Override
     // public void run(){
     // setLines();
     //}
     //});
     }

     public void setFont(Typeface typeFace){
         this.lines.setTypeface(字体);
         this.code.setTypeface(字体);
     }
     }

编辑:除了最近的发现,没有语法突出打字是快速的,但我仍然遇到延迟启用语法突出显示。 当我打开文件时,突出显示非常快,但打字速度仍然很慢,内存泄漏信息

04-28 04:49:58.119:D / dalvikvm(2437):GC_EXPLICIT释放185K,17%免费6027K / 7244K,暂停1ms + 1ms,总共5ms

出现。 无论如何,我想知道对象1字节数组(byte [],boolean [])是什么,因为它实际上使用2 MB。 有什么build议么?

编辑:

绝对find了问题。 由于文件很大,创build了大量的跨度,当我在文件的顶部改变某些东西时,editext必须重新计算所有跨度的位置。

Solutions Collecting From Web of "Android:EditText导致内存泄漏"

许多其他人面临着同样的问题。 这里有几点提示:

来自codeninja :

那么实际的解决scheme是什么? 避免在RelativeLayout中使用EditText,而是使用LinearLayout。 根据James的说法,如果你看DDMS,在input与RelativeLayout相关的文本时会发生很多重绘和重新计算。 所以这给我们提供了一个线索,确实是RelativeLayoutUpdate的问题:我忘了提及设置一个EditText的固定值会对性能有很大的帮助。 它防止重新计算和重新绘制布局。 感谢Giorgos Kylafas在下面的评论部分指出了这一点! 当涉及到Android性能技巧时,他还包含了对您有用的链接,所以我build议您阅读他的评论。

在第一种情况下,EditText的宽度是“wrap_content”。 每当你改变文本,即EditText的内容,视图需要重新测量和重新布局,这是缓慢的。 被包含在一个RelativeLayout中会让事情变得更糟,因为RelativeLayout总是多遍的。

在第二种情况下,EditText的宽度固定为“220 dip”。 它的测量和布局过程简单快捷。 另外你不使用“layout_weight”,所以它的父LinearLayout是单通的。 http://developer.android.com/guide/topics/ui/how-android-draws.html

从另一个stackoverflow 问题 :

避免在RelativeLayout中使用EditText,而是使用LinearLayout。

从另一个stackoverflow 问题 :

我有一个类似的问题,在ListView中使用EditText,通过使用加权宽度将EditText宽度更改为0dp来匹配/填充父级,可以解决此问题。

我不知道为什么会发生这种情况,但是我相信这是因为当EditText的宽度设置为包装内容时,它会调整/重绘本身,以便一切都合适,并且ListView也将尝试重绘自己一切都合适。 所以通过使EditText有一个固定的宽度,这个重绘不再是必需的。

总之:一定不要设置EditText的宽度来包装内容!