Android:EditText导致内存泄漏 [英] Android: EditText causing memory leak

查看:179
本文介绍了Android:EditText导致内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我首先要说的是,这是我第一次必须处理性能问题,因为这是我第一次开发android应用程序.

I want to start by saying that it's the first time that I have to deal with performance, because it's the first time that I develop an android app.

该应用程序是一个源代码编辑器,您可以在其中打开文件,对其进行修改并将其保存回去.该应用程序包含4个部分:

The app is a source code editor, where you can open files, modify them and save them back. The app consist of 4 parts:

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

完成基本代码编辑器后,我转向语法突出显示.现在,我想澄清一下,即使没有突出显示语法也会产生泄漏,所以这不是问题.

After I finished the base code editor, I moved to syntax highlighting. Now, I want to mke clear that the leaks are generated even without the syntax highlighting, so this is not the problem.

无论如何,通过测试语法高清晰度,我打开了大"文件(1200行代码),并且我注意到该应用程序变得非常慢,这很明显,因为我正在对整个文本进行正则表达式(我将避免这种情况)通过仅突出显示可见文本).这促使我在不使用大文件语法的情况下测试该应用程序,但我发现该应用程序仍然变得有点慢,并且我注意到发生了一些内存泄漏.

Anyway, by testing the syntax highlithing, I was opening "large" files (1200 lines of code) and I noticed that the app becomes extremly slow, which is obvious because I'm regexing the whole text (I will avoid this by highlight only the visible text). This push me to test the app without syntax highlithing with large files and I found that the app become still a bit slow and I noticed that some memory leaks happened.

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

In particular, when I open a large file (1200 lines of code) the app take 1 second to display the lines of code in the textview and when I type the drawing of the character is slow. In addition whenever I type of remove a character a memory leak happen.

我试图检查堆(使用MAT),但是正如我所说,我对此没有任何经验,我不确定该怎么做来调查这个问题.抱歉,我无法上传屏幕截图(对此没有stackoverflow的许可),但是我可以向您报告一些数字:

I tried to inspect the heap (with MAT), but as said I don't have any experience in this and I'm not sure what to do to investigate this problem. I'm sorry but I cannot upload screenshots (don't have permission by stackoverflow for that), but I can report you some numbers:

问题1

详细信息:

问题2

问题3

问题1 : 细节:

问题2 :

问题3问题4

在Android设备监视器上:

From the Android device monitor:

部分分配:

预先谢谢你

<?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对象是否很好.

Ok guys I found the problem. If you see, every time that I type something, I update the lines EditText and, since the text is long (1200 lines), it take a while to recompute it. Did event though about that! I have to find a faster way to show the lines of code. One option is to use one TextView for each line, in this way I only update the TextView that need to be changed. But I don't know if having 1200 TextView objects is nice.


    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);
    }
    }

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

Beside the recent discover, whithout syntax highlighting the typing is fast, but I still encounter lag when enabling the syntax highlighting. When I open the file, the highlight is very quick, but the typing is still slow and memory leak messages

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

04-28 04:49:58.119: D/dalvikvm(2437): GC_EXPLICIT freed 185K, 17% free 6027K/7244K, paused 1ms+1ms, total 5ms

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

appear. Anyway, I'm wondering what is the object 1-byte array (byte[], boolean[]) is, because it's actually using 2 MB. Any suggestions?

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

Definitely found the problem. Since the file is big and lot of spans are created, when I change something on the top of the file, the editext has to recalculate the position of all spans.

推荐答案

许多其他人也遇到了同样的问题.这里有一些提示:

many others faced your same problem. Here are a couple of hints:

来自 codeninja :

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

So what’s the actual solution? Avoid using EditText inside a RelativeLayout, use LinearLayout instead. According to James, If you look at the DDMS, a lot of redraws and recalculations occur while entering the text which is related to the RelativeLayout. So that gives us a clue the the problem is indeed the RelativeLayoutUpdate: I forgot to mention that setting a fixed with of an EditText will help a lot with the performance. It prevents re-calculation and re-drawing of layout. Thanks to Giorgos Kylafas for pointing it out in the comments section below! He also included links that can be useful for you when it comes to Android performance tips so I suggest reading his comment.

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

In the first case, EditText's width is "wrap_content". Everytime you change the text, i.e. EditText's content, the view needs to re-measure and re-layout, which is slow. Being contained insided a RelativeLayout makes things even worse, because RelativeLayout is always multi-pass.

在第二种情况下,EditText的宽度固定为"220 dip".它的 测量和布置通行证简单快捷.再加上你不使用 "layout_weight",因此其父级LinearLayout为单遍. http://developer.android.com/guide/topics/ui/how-android-draws.html

In the second case, EditText's width is fixed to "220 dip". Its measuring and layout pass is simple and quick. Plus you use no "layout_weight", so its parent LinearLayout is single-pass. http://developer.android.com/guide/topics/ui/how-android-draws.html

来自另一个stackoverflow 问题:

From another stackoverflow question:

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

Avoid using EditText inside a RelativeLayout, use LinearLayout instead.

来自另一个stackoverflow 问题:

From another stackoverflow question:

我在ListView中使用EditText遇到类似的问题, 通过使用加权宽度将EditText宽度更改为0dp进行修复 匹配/填充父级.

I was having a similar issue using EditText inside a ListView, that was fixed by changing the EditText width to 0dp using weighted widths to match/fill the parent.

我不确定为什么会这样,但是我相信是这样 因为当EditText的宽度设置为环绕内容时,它将 调整/重绘自身,使所有内容都适合,并且ListView将 还尝试重新绘制自己,以便适合所有情况.因此,通过 EditText具有固定的宽度,不再需要此重绘.

I don't know for sure why this was occurring, however I believe it is because when the width of the EditText is set to wrap content it will adjust/redraw itself so that everything fits, and the ListView will also attempt to redraw itself so everything fits. So by making the EditText have a fixed width, this redraw is no longer required.

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

In conclusion: be sure to not to set the width of the EditText to wrap-content!

这篇关于Android:EditText导致内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆