当前位置: 首页 > 知识库问答 >
问题:

Android:EditText导致内存泄漏

刁文光
2023-03-14

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

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

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

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

不管怎样,通过测试语法highlithing,我打开了“大型”文件(1200行代码),我注意到应用程序变得非常慢,这是很明显的,因为我正在重新生成整个文本(我将通过只突出显示可见的文本来避免这种情况)。这推动我测试应用程序没有语法高与大文件,我发现应用程序变得仍然有点慢,我注意到一些内存泄漏发生。

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

我尝试检查堆(使用MAT),但正如所说的,我没有这方面的任何经验,我不确定该做什么来调查这个问题。很抱歉,我不能上传截图(没有stackoverflow的权限),但我可以报告给你一些数字:

从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行),需要一段时间来重新计算它。事件虽然是关于那件事的!我必须找到一种更快的方法来显示代码行。一个选择是为每一行使用一个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。有什么建议吗?

编辑:

肯定找到问题了。由于文件很大,并且创建了很多跨距,当我更改文件顶部的内容时,编辑文本必须重新计算所有跨距的位置。

共有1个答案

陶富
2023-03-14

很多人也面临着你同样的问题。以下是一些提示:

来自Codeninja:

那么实际的解决方案是什么呢?避免在RelativeLayout中使用EditText,改用LinearLayout。根据James的说法,如果您查看DDMS,在输入与RelativeLayout相关的文本时会发生大量的重绘和重新计算。这给了我们一个线索,问题确实是相对的:我忘了提到,设置一个编辑文本的fixed with会对性能有很大帮助。防止重新计算和重新绘制布局。感谢Giorgos Kylafas在下面的评论部分指出!他还包括了一些链接,这些链接对你在谈到Android性能技巧时很有用,所以我建议你读一下他的评论。

在第一种情况下,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的宽度设置为wrap-content!

 类似资料:
  • 我有一些和等,但是我没有设置。你觉得会是那样吗? 你有什么想法或建议吗? PS:该应用程序在Ubuntu机器上运行 多谢.

  • 我正在玩rxjava,发现如果在活动被销毁之前没有完成订阅,则存在内存泄漏的风险,因为“可观察对象保留对上下文的引用”。如果订阅没有取消订阅,则此类情况的演示之一如下所示。已销毁(来源:https://github.com/dlew/android-subscription-leaks/blob/master/app/src/main/java/net/danlew/rxsubscriptions

  • 问题内容: 我正在编写一个测试程序,如下所示: 当用户单击按钮A时,它将打开50个JFrame。 当用户单击按钮B时,它将放置所有通过单击按钮A显示的JFrame。 我发现单击按钮B后内存不会减少。我使用任务管理器(在Windows中为+ + ,并检查“ java”的内存使用情况)确定了这一点。 问题答案: 是的,没有办法,无法解决(不仅在Java PL中), 1)实际上,不要在运行时/运行时创建

  • 严重:web应用程序创建了一个ThreadLocal,其键类型为[org.apache.log4j.helpers.ThreadLocalMap](值为[org.apache.log4j.helpers.ThreadLocalMap@3ac5b23e])和值类型为[java.util.Hashtable](值为[{userhost=192.168.15.90,userid=127,username

  • 我们在堆大小为512M的IBM J9 VM上运行weblogic服务器。 今天,服务器因OutOfMemory错误而失败。 我使用Eclipse Memory Analyzer打开了堆转储文件xxx.phd(安装了IBM DTFJ pluign以支持。phd文件)。 垫子给我一份泄漏嫌疑人报告,像这样: 我如何找到创建这个大数组的类? 或者任何帮助我识别大数组的提示?

  • 问题内容: 我正在运行django应用程序,其中包括matplotlib,并允许用户指定图形的轴。这可能会导致 “溢出错误:超出了Agg复杂度” 发生这种情况时,最多会占用100MB的RAM。通常,我会使用,和释放该内存,但是与该错误关联的内存似乎与该绘图对象无关。 有谁知道我该如何释放记忆? 谢谢。 这是一些给我Agg复杂度错误的代码。 问题答案: 我假设您可以至少运行一次您发布的代码。该问题仅