在Android中解析XML文件并在RecyclerView中显示

1. 引言

最近工作有解析外部xml文件在App中显示的需求,特来写篇文章记录一下,方便下次使用。

2. 准备工作

首先,在项目的AndroidManifest.xml文件中添加读取外部存储的权限声明。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

3. XML示例文件

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item>
        <number>1</number>
        <description>First item description</description>
    </item>
    <item>
        <number>2</number>
        <description>Second item description</description>
    </item>
</items>

4. 请求运行时权限

在你的Activity中,需要处理运行时权限请求。

private val requestPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
        if (isGranted) {
            readAndParseXmlFile()
        } else {
            Toast.makeText(this, "读取外部存储权限被拒绝", Toast.LENGTH_SHORT).show()
        }
    }

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    when {
        ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) ==
                PackageManager.PERMISSION_GRANTED -> {
            readAndParseXmlFile()
        }
        else -> {
            requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
        }
    }
}

5. 定义数据模型和适配器

定义一个数据类Item和一个RecyclerView的适配器ItemAdapter。

Item.kt

data class Item(val number: Int, val description: String)

ItemAdapter.kt

class ItemAdapter(private val items: MutableList<Item>) :
    RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {

    class ItemViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val textView = LayoutInflater.from(parent.context)
            .inflate(android.R.layout.simple_list_item_2, parent, false) as TextView
        return ItemViewHolder(textView)
    }

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val (number, description) = items[position]
        holder.textView.text = "$number - $description"
    }

    override fun getItemCount() = items.size

    fun addItem(item: Item) {
        items.add(item)
        notifyItemInserted(items.size - 1)
    }
}

6. 解析XML文件

义一个方法来解析XML文件,并在解析出新数据时即时更新RecyclerView。

private fun parseXmlAndUpdateRecyclerView(inputStream: InputStream) {
    try {
        val factory = XmlPullParserFactory.newInstance()
        factory.isNamespaceAware = true
        val parser = factory.newPullParser()
        parser.setInput(inputStream, null)

        var eventType = parser.eventType
        var currentNumber: Int? = null
        var currentDescription: String? = null

        while (eventType != XmlPullParser.END_DOCUMENT) {
            when (eventType) {
                XmlPullParser.START_TAG -> {
                    when (parser.name) {
                        "number" -> currentNumber = parser.nextText().toIntOrNull()
                        "description" -> currentDescription = parser.nextText()
                    }
                }
                XmlPullParser.END_TAG -> {
                    if (parser.name == "item" && currentNumber != null && currentDescription != null) {
                        val newItem = Item(currentNumber, currentDescription)
                        runOnUiThread {
                            adapter.addItem(newItem)
                        }
                        currentNumber = null
                        currentDescription = null
                    }
                }
            }
            eventType = parser.next()
        }

    } catch (e: Exception) {
        Log.e("XMLParser", "Error parsing XML", e)
        Toast.makeText(this, "解析XML文件失败: ${e.message}", Toast.LENGTH_SHORT).show()
    } finally {
        try {
            inputStream.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

7. 使用

在你的代码中直接调用readAndParseXmlFile方法,我是把xml文件直接放到了 sdcard目录下了,你也可以随意修改目录,注意不同安卓版本的权限问题,

    private fun readAndParseXmlFile() {
        try {
            // 修改为从SD卡根目录获取XML文件
            val xmlFile = File(Environment.getExternalStorageDirectory(), "data.xml")

            if (!xmlFile.exists()) {
                Log.e("XMLParser", "File does not exist.")
                Toast.makeText(this, "XML文件不存在", Toast.LENGTH_SHORT).show()
                return
            }

            FileInputStream(xmlFile).use { fis ->
                parseXmlAndUpdateRecyclerView(fis)
            }

        } catch (e: Exception) {
            Log.e("XMLParser", "Error reading XML file", e)
            Toast.makeText(this, "读取XML文件失败: ${e.message}", Toast.LENGTH_SHORT).show()
        }
    }

8.效果图

在这里插入图片描述


THE END

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值