【问题标题】:Store static data in Android - custom resource?在 Android 中存储静态数据 - 自定义资源?
【发布时间】:2017-02-25 01:22:01
【问题描述】:

我是 Android 开发的新手,我一直在玩弄它。我试图创建一个程序,该程序具有一个类似数据库的小型永不更改的数据集合。在我目前最好的语言 C# 中,我会使用自定义类的列表并将其序列化为 xml 文件,然后在运行时将其读入我的应用程序。我在 Android 中找到了 /xml 资源文件夹,但我不确定我将如何去做我所设想的事情。这样做的最佳方法是什么?

数据永远不需要更改。示例:

Blob   | A  | B
----------------
Blob 1 | 23 | 42
Blob 2 | 34 | 21

我知道它的布局像一个表,但使用数据库对我来说并没有什么意义,因为数据永远不会改变,我需要一种方法来存储它以最初填充数据库无论如何。

所以基本上我正在寻找一种方法来在我的应用程序中存储一些复杂的静态数据。有什么想法吗?

编辑:我还看到了 /raw 文件夹。所以我可以将东西存储在 /res/raw 或 /res/xml 中。但我不确定存储/解析数据的最佳方式是什么……

【问题讨论】:

    标签: android xml android-resources android-parser android-pullparser


    【解决方案1】:

    我认为这是最好的解决方案,我已经在使用它来在我的每个项目中存储静态数据。

    为此... 您可以做一件事,制作一个 xml 文件,即“temp.xml” ..并将数据存储在 temp.xml 中,如下所示:

      <?xml version="1.0" encoding="utf-8"?> 
    <rootelement1>
    
        <subelement> Blob 1  
         <subsubelement> 23 </subsubelement>
         <subsubelement> 42 </subsubelement> 
        </subelement>
    
        <subelement>Blob 2      
        <subsubelement> 34 </subsubelement>
        <subsubelement> 21 </subsubelement>
        </subelement>
    
    
        </rootelement1>
    

    然后使用 XML PullParser 技术来解析数据。 您可以在Example 上获得 PullParsing 技术的编码示例,请参阅此示例以获得更好的想法。

    享受!!

    【讨论】:

    • 是的,这就是我最终采用的技术,正如在接受答案的 cmets 上所讨论的那样。实际上,我发现这里的说明最适合 XmlPullParser:ibm.com/developerworks/opensource/library/x-android/index.html
    • 无法更新此 xml 字段值以在人修改它时更改。例如 Blob 1 sumit Sharma
    • @SumitSharma // 一旦文件位于 Asset 或 Resource 文件夹中,您将无法更改它。因为它是作为编译包烘焙的。您需要将其复制到 sdcard 或某处并进行修改。
    • 应该在哪里存储这个静态 XML 文件?我正在寻找一种在android中存储静态数据的方法,并考虑这样做。另外,这种方式仍然是首选方式吗? (因为这是几年前回答的)。
    【解决方案2】:

    最好的方法是使用Android Resource Heirarchy

    在 res/values/ 目录中,您可以存储多种基本数据类型的任意数量的键值对。在您的应用程序中,您将使用自动生成的资源 ID(基于资源键的名称)来引用它们。有关更多文档和详细信息,请参阅上面的链接。

    Android 还支持原始数据文件。您可以将数据存储在 res/raw/yourfile.dat 下的文件目录中

    您可以以任何您想要的基于文本的格式创建数据,然后在活动启动时使用资源访问 API 读取它。

    【讨论】:

    • 这会比将其存储在 xml 表单中并读取它更好还是更糟?如果我确实使用了 xml 表单,我将如何阅读它?
    • @NickAldwin 更好的是你可以以任何你想要的格式存储,更糟糕的是你没有内置的 API 来解析数据。您还可以使用更好的资源层次结构。我会用详细信息编辑我的帖子。
    • 我对 res/values/ 的担心是我不打算仅以一对一的形式存储数据(如上例所示)。那么除了您发布的链接中指定的层次结构中的那些之外,是否有内置的 api 用于解析 xml 文件?编辑: TypedArray 是否适用于自定义类(如上面的“Blob”示例)?这会是要走的路吗?
    • 啊,我以前见过,但没有深入研究。谢谢!所以这是一个很好的方法。我不想打破任何惯例......
    【解决方案3】:

    我过去曾使用 Simple 进行 xml 解析。如果您知道在 xml 中会发生什么,我认为它的代码量最少,在您的情况下您就是这样做的。

    http://simple.sourceforge.net/

    【讨论】:

      【解决方案4】:

      根据doc/xml是要走的路。

      Providing Resources

      xml/ 可以在运行时通过调用读取的任意 XML 文件

      Resources.getXML().
      

      这里必须保存各种XML配置文件,比如可搜索的配置。

      Documentation for getXML()

      我还做了一个工作示例:

      • XML 结构:

        <?xml version="1.0" encoding="utf-8"?>
        <quizquestions>
            <quizquestion>
                <header_image_src>ic_help_black_24dp</header_image_src>
                <question>What is the Capital of U.S.A.?</question>
                <input_type>Radio</input_type>
                <answer correct="false">New York City</answer>
                <answer correct="true">Washington D.C.</answer>
                <answer correct="false">Chicago</answer>
                <answer correct="false">Philadelphia</answer>
            </quizquestion>
        
            <quizquestion>
                <header_image_src>ic_help_black_24dp</header_image_src>
                <question>What is the family name of the famous dutch painter Vincent Willem van .... ?</question>
                <input_type>EditText</input_type>              
                <answer correct="true">Gogh</answer>
            </quizquestion>
        </quizquestions>
        
      • 保存解析数据的 Java 类:

        public class QuizQuestion {
            private int headerImageResId;
            private String question;
            private String inputType;
            private ArrayList<String> answers;
            private ArrayList<Boolean> answerIsCorrect;
            private ArrayList<Integer> correctAnswerIndexes;
        
            /**
             * constructor for QuizQuestion object
             */
            QuizQuestion() {
                headerImageResId = 0;
                question = null;
                inputType = null;
                answers = new ArrayList<>();
                answerIsCorrect = new ArrayList<>();
                correctAnswerIndexes = new ArrayList<>();
            }
        
        
            public void setHeaderImageResId(int headerImageResId) {
                this.headerImageResId = headerImageResId;
            }
        
            public int getHeaderImageResId() {
                return headerImageResId;
            }
        
        
            void setQuestion(String question) {
                this.question = question;
            }
        
            public String getQuestion() {
                return question;
            }
        
        
            void setInputType(String inputType) {
                this.inputType = inputType;
            }
        
            public String getInputType() {
                return inputType;
            }
        
            void addAnswer(String answer, boolean isCorrect)
            {
                if (isCorrect)
                    correctAnswerIndexes.add(answers.size());
                answers.add(answer);
                answerIsCorrect.add(isCorrect);
            }
        
        
            public ArrayList<String> getAnswers() {
                return answers;
            }
        
            public String getAnswer(int index)
            {
                // check index to avoid out of bounds exception
                if (index < answers.size()) {
                    return answers.get(index);
                }
                else
                {
                    return null;
                }
            }
        
            public int size()
            {
                return answers.size();
            }
        
        }
        
      • 解析器本身:

        /**
         * Created by bivanbi on 2017.02.23..
         *
         * class to parse xml resource containing quiz data into ArrayList of QuizQuestion objects
         *
         */
        
        public class QuizXmlParser {
        
            public static String lastErrorMessage = "";
        
            /**
             * static method to parse XML data into ArrayList of QuizQuestion objects
             * @param activity is the calling activity
             * @param xmlResourceId is the resource id of XML resource to be parsed
             * @return null if parse error is occurred or ArrayList of objects if successful
             * @throws XmlPullParserException
             * @throws IOException
             */
            public static ArrayList<QuizQuestion> parse(Activity activity, int xmlResourceId)
                    throws XmlPullParserException, IOException
            {
                String logTag = QuizXmlParser.class.getSimpleName();
                Resources res = activity.getResources();
                XmlResourceParser quizDataXmlParser = res.getXml(R.xml.quiz_data);
        
                ArrayList<String> xmlTagStack = new ArrayList<>();
                ArrayList<QuizQuestion> quizQuestions = new ArrayList<>();
        
                QuizQuestion currentQuestion = null;
        
                boolean isCurrentAnswerCorrect = false;
        
                quizDataXmlParser.next();
                int eventType = quizDataXmlParser.getEventType();
                while (eventType != XmlPullParser.END_DOCUMENT)
                {
                    //  begin document
                    if(eventType == XmlPullParser.START_DOCUMENT)
                    {
                        Log.d(logTag,"Begin Document");
                    }
                    //  begin tag
                    else if(eventType == XmlPullParser.START_TAG)
                    {
                        String tagName = quizDataXmlParser.getName();
                        xmlTagStack.add(tagName);
                        Log.d(logTag,"Begin Tag "+tagName+", depth: "+xmlTagStack.size());
                        Log.d(logTag,"Tag "+tagName+" has "+quizDataXmlParser.getAttributeCount()+" attribute(s)");
        
                        // this is a beginning of a quiz question tag so create a new QuizQuestion object
                        if (tagName.equals("quizquestion")){
                            currentQuestion = new QuizQuestion();
                        }
                        else if(tagName.equals("answer"))
                        {
                            isCurrentAnswerCorrect = quizDataXmlParser.getAttributeBooleanValue(null,"correct",false);
                            if (isCurrentAnswerCorrect == true) {
                                Log.d(logTag, "Tag " + tagName + " has attribute correct = true");
                            }
                            else
                            {
                                Log.d(logTag, "Tag " + tagName + " has attribute correct = false");
                            }
                        }
                    }
                    //  end tag
                    else if(eventType == XmlPullParser.END_TAG)
                    {
                        String tagName = quizDataXmlParser.getName();
                        if (xmlTagStack.size() < 1)
                        {
                            lastErrorMessage = "Error 101: encountered END_TAG "+quizDataXmlParser.getName()+" while TagStack is empty";
                            Log.e(logTag, lastErrorMessage);
                            return null;
                        }
                        xmlTagStack.remove(xmlTagStack.size()-1);
                        Log.d(logTag,"End Tag "+quizDataXmlParser.getName()+", depth: "+xmlTagStack.size());
        
                        //  reached the end of a quizquestion definition, add it to the array
                        if (tagName.equals("quizquestion")){
                            if (currentQuestion != null)
                                quizQuestions.add(currentQuestion);
                            currentQuestion = null;
                        }
                    }
                    //  text between tag begin and end
                    else if(eventType == XmlPullParser.TEXT)
                    {
                        String currentTag = xmlTagStack.get(xmlTagStack.size()-1);
                        String text = quizDataXmlParser.getText();
                        Log.d(logTag,"Text: "+text+", current tag: "+currentTag+", depth: "+xmlTagStack.size());
        
                        if (currentQuestion == null) {
                            Log.e(logTag,"currentQuestion is not initialized! text: "+text+", current tag: "+currentTag+", depth: "+xmlTagStack.size());
                            continue;
                        }
        
                        if (currentTag.equals("header_image_src"))
                        {
                            int drawableResourceId = activity.getResources().getIdentifier(text, "drawable", activity.getPackageName());
                            currentQuestion.setHeaderImageResId(drawableResourceId);
                        }
                        else if (currentTag.equals("question"))
                        {
                            currentQuestion.setQuestion(text);
                        }
                        else if (currentTag.equals("answer"))
                        {
                            currentQuestion.addAnswer(text, isCurrentAnswerCorrect);
                        }
                        else if (currentTag.equals("input_type"))
                        {
                            currentQuestion.setInputType(text);
                        }
                        else
                        {
                            Log.e(logTag,"Unexpected tag "+currentTag+" with text: "+text+", depth: "+xmlTagStack.size());
                        }
                    }
                    eventType = quizDataXmlParser.next();
                }
                Log.d(logTag,"End Document");
                return quizQuestions;
            }
        
        }
        
      • 最后,调用解析器:

        //  read quiz data from xml resource quiz_data
        try {
            quizQuestions = QuizXmlParser.parse(this,R.xml.quiz_data);
            Log.d("Main","QuizQuestions: "+quizQuestions);
        
        } catch (XmlPullParserException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            quizQuestions = null;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            quizQuestions = null;
        }
        
        if (quizQuestions == null)
        {
            Toast.makeText(this,"1001 Failed to parse Quiz XML, sorry", Toast.LENGTH_LONG).show();
            finish();
        }
        

      【讨论】:

        猜你喜欢
        • 2023-02-22
        • 1970-01-01
        • 2015-02-05
        • 1970-01-01
        • 1970-01-01
        • 2022-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多