Android:EditText导致内存泄漏

Chr*_*r A 10 java android memory-leaks

我想首先说这是我第一次处理性能,因为这是我第一次开发Android应用程序.

该应用程序

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

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

问题

完成基本代码编辑器后,我转到语法高亮.现在,我想明确表示即使没有语法突出显示也会产生泄漏,所以这不是问题所在.

无论如何,通过测试语法highlithing,我打开"大"文件(1200行代码),我注意到应用程序变得非常慢,这是显而易见的,因为我正在整理整个文本(我将通过仅突出显示来避免这种情况)可见的文字).这促使我测试应用程序没有语法高度大文件,我发现应用程序变得有点慢,我发现一些内存泄漏发生.

特别是,当我打开一个大文件(1200行代码)时,应用程序需要1秒钟才能在textview中显示代码行,当我输入字符的绘图时速度很慢.此外,每当我键入删除字符时,都会发生内存泄漏.

检验

我试图检查堆(使用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>
Run Code Online (Sandbox Code Playgroud)

编辑

好的,我发现了这个问题.如果你看到,每次输入内容时,我都会更新EditText行,因为文本很长(1200行),所以需要一段时间来重新计算它.事情虽然关于那个!我必须找到一种更快的方式来显示代码行.一种选择是为每一行使用一个TextView,这样我只更新需要更改的TextView.但我不知道是否有1200个TextView对象是好的.

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

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

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

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

    import java.util.ArrayList;

    /**
     * Created by Green on 26/02/15.
     */
    public class CodeEditView extends LinearLayout {

        private Context context;
        private TextView lines;
        private EditText code;
        private Typeface currentTypeface;
        private InternalFile internalFile;
        private Lexer lexer;
        private Colorizer colorizer;

        public CodeEditView(Context context) {
            super(context);
            this.context = context;
            init(null);
        }   

        public CodeEditView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
            init(attrs);
        }

        private void init(AttributeSet attrs) {
            //CHECK THIS
            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 = new 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() {



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

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

            @Override
            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: tokens) {
    //            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(typeFace);
        this.code.setTypeface(typeFace);
    }
    }

编辑:除了最近的发现,没有语法突出显示键入速度很快,但在启用语法高亮时我仍然遇到延迟.当我打开文件时,突出显示非常快,但输入仍然很慢并且内存泄漏消息

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

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

编辑:

绝对找到了问题所在.由于文件很大并且创建了很多跨度,当我在文件顶部更改某些内容时,editext必须重新计算所有跨度的位置.

Mat*_*att 3

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

\n\n

来自代码忍者

\n\n
\n

那么\xe2\x80\x99s 的实际解决方案是什么呢?避免在RelativeLayout 中使用EditText,而使用LinearLayout。根据 James 的说法,如果您查看 DDMS,就会发现在输入与relativelayout 相关的文本时会发生大量重绘和重新计算。因此,这给了我们一个线索,问题确实是RelativeLayoutUpdate:我忘记提及设置 EditText 的固定值将对性能有很大帮助。它可以防止重新计算和重新绘制布局。\n 感谢 Giorgos Kylafas 在下面的评论\n 部分指出这一点!他还提供了在涉及 Android 性能技巧时对您有用的链接,因此我建议您阅读他的评论。

\n\n

在第一种情况下,EditText 的宽度是“wrap_content”。每次更改文本(即 EditText 的内容)时,视图都需要重新测量并重新布局,这很慢。包含在RelativeLayout 中会使事情变得更糟,因为RelativeLayout 总是多通道的。

\n\n

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

\n
\n\n

来自另一个 stackoverflow问题

\n\n
\n

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

\n
\n\n

来自另一个 stackoverflow问题

\n\n
\n

我在 ListView 中使用 EditText 时遇到了类似的问题,该问题已通过使用加权宽度将 EditText 宽度更改为 0dp 来匹配/填充父级来解决。

\n\n

我不确定为什么会发生这种情况,但我相信这是因为当 EditText 的宽度设置为换行内容时,它会调整/重绘自身,以便一切都适合,并且 ListView 将\ n 还尝试重新绘制自身,以便一切都适合。因此,通过使 EditText 具有固定宽度,不再需要此重绘。

\n
\n\n

结论:一定不要将EditText的宽度设置为wrap-content!

\n