繁体   English   中英

Android-处理大量XML数据-I / art:释放了后台部分并发标记清除GC

[英]Android - Working with a lot of XML Data - I/art: Background partial concurrent mark sweep GC freed

在我的项目中,我将使用许多XML数据,例如:

<person>
    <name>Alex</name>
    <data1>data1</data1>
    <data2>data2</data2>
    <data3>data3</data3>
</person>

<person>
    <name>paul</name>
    <data1>data1</data1>
    <data2>data2</data2>
    <data3>data3</data3>
</person>

这些XML文件有600多个条目。 我用片段称呼它们的站点,然后将它们加载很长时间并抛出:“ I / Choreographer:跳过了47帧!该应用程序可能在其主线程上做了大量工作。” 我已经知道如何通过启动另一个线程来解决此问题。 仍然需要花费几秒钟来打开页面,并且我实现的“关键字搜索”导致Android Monitor抛出“ I / art:后台部分并发标记清除GC已释放83556(6MB)AllocSpace对象,834(16MB)LOS对象,每3次一样45%的免费空间,19MB / 35MB,暂停296us共124.540ms“。 我已经读过有关多数民众赞成的事情,但是应该避免。

由于我还是Android的新手,所以我想知道我做的是否正确,还是可以使用数据库更好地处理数据。

private static String getValue(String tag, Element element) {
    NodeList nodeList = element.getElementsByTagName(tag).item(0).getChildNodes();
    Node node = nodeList.item(0);
    return node.getNodeValue();
}



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    //return inflater.inflate(R.layout.fragment_coffee_pref, container, false);
    final View view =  inflater.inflate(R.layout.fragment_coffee_pref, container, false);

    try {
        // get XML file
        AssetManager assetManager = getActivity().getAssets();

        if(Locale.getDefault().getLanguage().equals("de")){
            is = assetManager.open("coffee_pref_DE.xml");
        }else{
            is = assetManager.open("coffee_pref.xml");
        }


        //init XML parser
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(is);

        Element element=doc.getDocumentElement();
        element.normalize();

        // init table
        LinearLayout CPcontainer = (LinearLayout) view.findViewById(R.id.CPcontainer);
        TableRow.LayoutParams w50Layout = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT,0.50f);
        TableRow.LayoutParams w100Layout = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT,1.0f);
        //paramsExample.setMargins(2, 2, 2, 2); // (left, top, right, bottom);

        // go throught XML List and insert rows for each entry
        NodeList nList = doc.getElementsByTagName("person");

        for (int i=0; i<nList.getLength(); i++) {

            Node node = nList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {

                TableLayout tableLayout = new TableLayout(getActivity());
                tableLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));// assuming the parent view is a LinearLayout

                TableRow row1= new TableRow(getActivity());
                TableRow row2= new TableRow(getActivity());
                TableRow row3= new TableRow(getActivity());
                TableRow row4= new TableRow(getActivity());
                TableRow.LayoutParams lp = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT);
                row1.setLayoutParams(lp);
                row2.setLayoutParams(lp);
                row3.setLayoutParams(lp);
                row4.setLayoutParams(lp);

                Element element2 = (Element) node;

                // row 1
                TextView tvName = new TextView(getActivity());
                tvName.setLayoutParams(w100Layout);
                tvName.setText(Html.fromHtml("<a href=\""+getValue("link", element2)+"\">"+getValue("name", element2)+"</a>"));
                tvName.setMovementMethod(LinkMovementMethod.getInstance());
                tvName.setBackgroundResource(R.drawable.head_shape);
                tvName.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                row1.addView(tvName);
                tableLayout.addView(row1);

                // row 2
                TextView tvData1 = new TextView(getActivity());
                tvData1.setLayoutParams(w50Layout);
                tvData1.setText(getValue("data1", element2));
                tvData1.setBackgroundResource(R.drawable.cell_shape);
                tvData1.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                TextView textData1 = new TextView(getActivity());
                textData1.setText(R.string.tableData1);
                textData1.setLayoutParams(w50Layout);
                //textData1.setTypeface(null, Typeface.BOLD);
                textData1.setBackgroundResource(R.drawable.cell_shape);
                textData1.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                row2.addView(textData1);
                row2.addView(tvData1);
                tableLayout.addView(row2);

                // row3
                TextView tvData2 = new TextView(getActivity());
                tvData2.setLayoutParams(w50Layout);
                tvData2.setText(getValue("data2", element2));
                tvData2.setBackgroundResource(R.drawable.cell_shape);
                tvData2.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                TextView textData2 = new TextView(getActivity());
                textData2.setText(R.string.tableData2);
                textData2.setLayoutParams(w50Layout);
                //textData2.setTypeface(null, Typeface.BOLD);
                textData2.setBackgroundResource(R.drawable.cell_shape);
                textData2.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                row3.addView(textData2);
                row3.addView(tvData2);
                tableLayout.addView(row3);

                // row 4
                TextView tvData3 = new TextView(getActivity());
                tvData3.setLayoutParams(w50Layout);
                tvData3.setText(getValue("sugar", element2));
                tvData3.setBackgroundResource(R.drawable.cell_shape);
                tvData3.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                TextView textData3 = new TextView(getActivity());
                textData3.setText(R.string.tableData3);
                textData3.setLayoutParams(w50Layout);
                //textData3.setTypeface(null, Typeface.BOLD);
                textData3.setBackgroundResource(R.drawable.cell_shape);
                textData3.setPadding(30, 20, 30, 20); // (left, top, right, bottom);

                row4.addView(textData3);
                row4.addView(tvData3);
                tableLayout.addView(row4);

                // add table to layout
                CPcontainer.addView(tableLayout);
            }

        }


    } catch (Exception e) {e.printStackTrace();}


    searchforName = (EditText) view.findViewById(R.id.searchForName);

    searchforName.addTextChangedListener(new TextWatcher() {

        public void afterTextChanged(Editable s) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {

                String searchedName = searchforName.getText().toString().toLowerCase();

                    LinearLayout CPcontainer = (LinearLayout) view.findViewById(R.id.CPcontainer);
                    for (int i = 1, j = CPcontainer.getChildCount(); i < j; i++) {
                        View view2 = CPcontainer.getChildAt(i);
                        if(view2 instanceof TableLayout) {
                            TableLayout table2 = (TableLayout) view2;

                                TableRow row2 = (TableRow) table2.getChildAt(0);
                                if (!TextUtils.isEmpty(searchedName)) {
                                    TextView searchableName = (TextView) row2.getChildAt(0);
                                    String sName = Html.fromHtml(searchableName.getText().toString()).toString();
                                    if (sName.startsWith(searchedName) || sName.equals(searchedName)) {
                                        //if (sName.toLowerCase().contains(searchedName)) {
                                        table2.setVisibility(View.VISIBLE);
                                    } else {
                                        table2.setVisibility(View.GONE);
                                    }
                                } else {
                                    table2.setVisibility(View.VISIBLE);
                                }
                            }
                    }
                }
            });


        }

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

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

    return view;
}

另外,由于我已经在名称TextView中实现了HTML链接,因此无法搜索它了,也无法解决该问题。

String sName = Html.fromHtml(searchableName.getText().toString()).toString();

对于我的问题的所有帮助或信息,我将深表感谢!

XML解析通常对于大型文档来说是令人讨厌的-您创建了许多小对象,这在垃圾收集器中造成了很多破坏。 试图最小化对象创建的库可以提供帮助,但是它总是很糟糕的。

因此,我不会真正担心GC警告。 最后,您不会遇到OOM或造成泄漏。 对于编舞者警告-解析大型文档时,请在另一个线程或AsyncTask上执行此操作。 然后,主UI线程可以继续正常处理。 解析完成后,将事件发送到主线程以进行任何UI更改。

很可能您的文档解析器很慢,无法解析XML。 如果条目太多,则有两种选择:

  1. 查看您是否可以通过防止进行验证等来提高构建器的性能。(请参阅以下链接,将其作为一种方法: https : //jdevel.wordpress.com/2011/03/28/java-documentbuilder-xml-parsing-is-very-慢/ )。 我建议将其包装在代码中以出于调试目的启用/禁用它。

  2. 研究DOM和SAX之间的区别( SAX和DOM之间有什么区别? )-您可能想要并且能够使用SAX方法。

  3. 希望改变数据的组织方式和/或将其拆分为不同的文件。

最后,XML已经到位了,但是如果性能是最高优先级,那么也许您应该使用其他文件格式,然后在构建定制解决方案时可以根据您的需要优化文档结构/传输/解析(通常仅用于非常复杂的情况)。 /高级工作,如果可能应避免)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM