Android:EditText导致内存泄漏

时间:2015-04-27 21:01:25

标签: java android memory-leaks

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

该应用

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

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

问题

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

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

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

检查

我试图检查堆(使用MAT),但正如我所说,我没有任何经验,我不知道如何调查这个问题。对不起,我无法上传截图(没有stackoverflow的权限),但我可以报告一些数字:

打开大文件之前的系统

系统概述

enter image description here

泄露嫌疑人

enter image description here

问题1 enter image description here

详细说明: enter image description here

问题2 enter image description here

问题3 enter image description here

最大的顶级支配者套餐

enter image description here enter image description here

最大的对象

enter image description here

打开大文件后的系统

系统概述

enter image description here

泄露嫌疑人:

enter image description here

问题1 enter image description here 细节: enter image description here

问题2 enter image description here

问题3问题4 enter image description here

最大的顶级支配者套餐

enter image description here enter image description here

最大的对象

enter image description here

从Android设备监视器:

打开大文件之前的系统

enter image description here

打开大文件后的系统

enter image description here

分配的某些部分:

enter image description here enter image description here enter image description here 提前谢谢

编辑:

<?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行),所以需要一段时间来重新计算它。事情虽然关于那个!我必须找到一种更快的方式来显示代码行。一种选择是为每一行使用一个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必须重新计算所有跨度的位置。

1 个答案:

答案 0 :(得分:3)

许多其他人面临同样的问题。以下是一些提示:

来自codeninja

  

那么实际的解决方案是什么?避免在里面使用EditText   RelativeLayout,改为使用LinearLayout。据詹姆斯说,如果你   看看DDMS,会发生很多重绘和重新计算   输入与RelativeLayout相关的文本。以便   给我们一个线索,问题确实是RelativeLayoutUpdate:I   忘了提一下用EditText设置一个固定的东西会有帮助   很多表现。它可以防止重新计算和重新绘制   布局。感谢Giorgos Kylafas在评论中指出了这一点   以下部分!他还包括可能对您有用的链接   它涉及Android性能提示,所以我建议阅读他的评论。

     

在第一种情况下,EditText的宽度为&#34; wrap_content&#34;。每次你   更改文本,即EditText的内容,视图需要重新测量   并重新布局,这很慢。被包含在内   RelativeLayout让事情变得更糟,因为RelativeLayout是   总是多次通过。

     

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

来自另一个stackoverflow question

  

避免在RelativeLayout中使用EditText,请使用LinearLayout   代替。

来自另一个stackoverflow question

  

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

     

我不确定为什么会这样,但我相信它是   因为当EditText的宽度设置为包装内容时,它将   调整/重绘自身,以便一切都适合,ListView将   也试图重绘自己所以一切都适合。所以通过制作   EditText具有固定的宽度,不再需要重绘。

总之:务必不要将EditText的宽度设置为wrap-content!