You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin开发故事书App遇lateinit未初始化错误(HomeFragment)求助

问题描述

我是Kotlin编程新手,正在开发一款故事书App,计划在HomeFragment中通过本地JSON文件(从Assets加载)结合Glide加载数据,但运行时出现错误:lateinit property itemsList has not been initialized,附上相关代码,请求帮助解决。

错误信息

lateinit property itemsList has not been initialized

HomeFragment 代码

class HomeFragment : Fragment() {

    private lateinit var bookAdapter: BookAdapter
    private lateinit var recyclerView: RecyclerView
    private lateinit var itemsList: ArrayList<BooksData>

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        val view = inflater.inflate(R.layout.fragment_home, container, false)

        // Initialize the RecyclerView
        recyclerView = view.findViewById(R.id.bookRecyclerView)
        recyclerView.layoutManager = GridLayoutManager(requireContext(), 2)
        bookAdapter = BookAdapter(this@HomeFragment, itemsList)
        recyclerView.adapter = bookAdapter
        recyclerView.setHasFixedSize(true)
        itemsList = ArrayList<BooksData>()
        loadData()
        return view
    }

    private fun loadData() {
        val jsonString = loadJson("contents.json")
        val items = parseJson(jsonString)
        bookAdapter.setData(items)
    }

    private fun loadJson(contents: String): String {
        val inputStream = requireContext().assets.open(contents)
        val size = inputStream.available()
        val buffer = ByteArray(size)
        inputStream.read(buffer)
        inputStream.close()
        return String(buffer)
    }

    private fun parseJson(jsonString: String): ArrayList<BooksData> {
        val jsonArray = JSONArray(jsonString)
        val items = ArrayList<BooksData>()
        for (i in 0 until jsonArray.length()) {
            val jsonObject = jsonArray.getJSONObject(i)
            val imageUrl = jsonObject.getString("imageUrl")
            val bookName = jsonObject.getString("bookName")
            items.add(BooksData(imageUrl, bookName))
        }; return items
    }
}

数据类代码

data class BooksData(val bookName:String, val imageUrl:String){
}

适配器类代码

class BookAdapter(var context: HomeFragment, private var dataList: ArrayList<BooksData>) :
    RecyclerView.Adapter<BookAdapter.BookViewHolder>() {

    inner class BookViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var bookNameTextView: TextView = itemView.findViewById(R.id.bookName)
        var bookImageView: ImageView = itemView.findViewById(R.id.imageUrl)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookViewHolder {
        val view =
            LayoutInflater.from(parent.context).inflate(R.layout.book_category_item, parent, false)
        return BookViewHolder(view)
    }

    override fun getItemCount(): Int = dataList.size
    fun setData(data: ArrayList<BooksData>) {
        dataList.clear()
        dataList.addAll(data)
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: BookViewHolder, position: Int) {
        val item = dataList[position]
        holder.bookNameTextView.text = item.bookName
        Glide.with(context).load(item.imageUrl).placeholder(R.drawable.ic_launcher_background)
            .error(R.drawable.vec_quiz).into(holder.bookImageView)
    }
}

JSON文件内容

{
"items": [
{
"bookName": "Basic Grammar",
"imageUrl": "https://drive.google.com/uc?id=1_eVoTO4IeTW1gAbNBb_0-GWASecBNGgS"
    } ,
    {
      "bookName": "Basic Grammar",
      "imageUrl": "https://drive.google.com/uc?id=1_eVoTO4IeTW1gAbNBb_0-GWASecBNGgS"
    }
]
}

修复方案

1. 解决itemsList未初始化的核心问题

错误根源是创建BookAdapter时,itemsList还没被初始化——你先调用了BookAdapter(this@HomeFragment, itemsList),之后才给itemsList赋值,违反了lateinit变量必须先初始化再使用的规则。

调整onCreateView中的代码顺序,先初始化itemsList再创建适配器:

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
    val view = inflater.inflate(R.layout.fragment_home, container, false)

    // 先初始化itemsList
    itemsList = ArrayList<BooksData>()
    // 初始化RecyclerView相关
    recyclerView = view.findViewById(R.id.bookRecyclerView)
    recyclerView.layoutManager = GridLayoutManager(requireContext(), 2)
    bookAdapter = BookAdapter(this@HomeFragment, itemsList)
    recyclerView.adapter = bookAdapter
    recyclerView.setHasFixedSize(true)
    loadData()
    return view
}

2. 修复JSON解析错误

你的JSON外层是包含items数组的对象,但当前parseJson方法直接把整个JSON字符串当作数组解析,会抛出格式异常。修改解析逻辑:

private fun parseJson(jsonString: String): ArrayList<BooksData> {
    val rootObj = JSONObject(jsonString)
    val jsonArray = rootObj.getJSONArray("items")
    val items = ArrayList<BooksData>()
    for (i in 0 until jsonArray.length()) {
        val itemObj = jsonArray.getJSONObject(i)
        val bookName = itemObj.getString("bookName")
        val imageUrl = itemObj.getString("imageUrl")
        // 注意BooksData构造参数顺序是bookName在前,避免传反
        items.add(BooksData(bookName, imageUrl))
    }
    return items
}

3. 优化适配器上下文传递(可选)

适配器直接持有HomeFragment实例存在内存泄漏风险,建议改为传递Context:

  • 修改适配器构造函数:
class BookAdapter(var context: Context, private var dataList: ArrayList<BooksData>) :
    RecyclerView.Adapter<BookAdapter.BookViewHolder>() {
  • 创建适配器时传入上下文:
bookAdapter = BookAdapter(requireContext(), itemsList)

4. 避免lateinit潜在风险(可选)

如果不想使用lateinit,可以直接初始化itemsList:

private var itemsList: ArrayList<BooksData> = arrayListOf()

这样就无需担心未初始化问题。

内容的提问来源于stack exchange,提问作者Anoop Moji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:43:18