Android - 使用大量XML数据 - I / art:后台部分并发标记扫描GC释放

时间:2017-01-21 16:30:04

标签: java android

在我的项目中,我将使用大量的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监视器丢失 “我/艺术:背景部分并发标记扫描GC释放83556(6MB)AllocSpace对象,834(16MB)LOS对象,45%免费,19MB / 35MB,暂停296us总计124.540ms” 像每第3次一样。我已经读到这是正常的事情,但应该避免。

由于我还不熟悉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();

我会感谢每一个关于我的问题的帮助或信息!

2 个答案:

答案 0 :(得分:0)

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

所以我不会真的担心GC警告。最后,你不会去OOM或导致泄密。对于chorographer警告 - 在解析大型文档时,在另一个线程或AsyncTask上执行此操作。然后主UI线程可以继续正常处理。完成解析后,将事件发送到主线程以进行任何UI更改。

答案 1 :(得分:0)

您很可能有一个缓慢的DocumentBuilder来解析您的XML。如果您有这么多条目,您有几个选择:

  1. 查看是否可以通过阻止验证等来提高构建器性能(请将此链接视为一种方法:https://jdevel.wordpress.com/2011/03/28/java-documentbuilder-xml-parsing-is-very-slow/)。我建议在代码中包装它以启用/禁用它以进行调试。

  2. 调查DOM和SAX(What is the difference between SAX and DOM?)之间的差异 - 您可能希望并能够使用SAX方法。

  3. 查看更改数据的组织方式和/或将其拆分为不同的文件。

  4. 最后,XML已经占据了它的位置但是如果性能是最高优先级,那么你应该使用不同的文件格式,那么如果你构建一个自定义解决方案,可以根据你的需要优化文档结构/传输/解析(通常这只适用于非常强烈/高级的工作,如果可能的话应该避免。)

相关问题