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

在InformationFragment中应向AdapterItem传递何种Context?

Android Fragment中实例化RecyclerView Adapter的Context传递问题

问题场景

在InformationFragment中通过Retrofit获取数据后,需要实例化AdapterItem,但不清楚该向其构造方法传递什么Context(无法使用baseContext),相关代码如下:

AdapterItem 原代码

class AdapterItem(val context: Context, val userList: List) : RecyclerView.Adapter<AdapterItem.ViewHolder>() {

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var numeLista: TextView
        var caloriiLista: TextView

        init {
            numeLista = itemView.numeLista
            caloriiLista = itemView.caloriiLista
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        var itemView = LayoutInflater.from(context).inflate(R.layout.row_items, parent, false)
        return ViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.numeLista.text = userList[position].foodItems.get(0).foodName
        holder.caloriiLista.text = userList[position].foodItems.get(0).calories.toString()
    }

    override fun getItemCount(): Int {
        return userList.size
    }
}

InformationFragment 原代码

const val BASE_URL = "https://raw.githubusercontent.com/terrenjpeterson/caloriecounter/master/src/data/"

class InformationFragment : Fragment() {

    private var binding: FragmentInformationBinding? = null
    private val sharedViewModel: SharedViewModel by activityViewModels()

    lateinit var adapterItem: AdapterItem
    lateinit var linearLayoutManager: LinearLayoutManager

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 原代码存在空指针隐患:未初始化binding就操作recyclerview_lista
        recyclerview_lista.setHasFixedSize(true)
        linearLayoutManager = LinearLayoutManager(this.context)
        recyclerview_lista.layoutManager = linearLayoutManager

        getMyData()

        val fragmentBinding = FragmentInformationBinding.inflate(inflater, container, false)
        binding = fragmentBinding
        return fragmentBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding?.apply {
            viewModel = sharedViewModel
            informationFragment = this@InformationFragment
            lifecycleOwner = viewLifecycleOwner
        }
    }

    private fun getMyData() {
        val retrofitBuilder = Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(BASE_URL)
            .build()
            .create(ApiInterface::class.java)

        val retrofitData = retrofitBuilder.getData()

        retrofitData.enqueue(object : Callback<List<MyDataItem>?> {
            override fun onResponse(
                call: Call<List<MyDataItem>?>,
                response: Response<List<MyDataItem>?>
            ) {
                val responseBody = response.body()!!
                adapterItem = AdapterItem(, responseBody) // 此处Context参数缺失
                adapterItem.notifyDataSetChanged()
                recyclerview_list.adapter = adapterItem
            }

            override fun onFailure(call: Call<List<MyDataItem>?>, t: Throwable) {
                Log.d("informationFragment", "onFailure: " + t.message)
            }
        })
    }
}

解决方案

方案1:优化Adapter,移除构造方法中的Context参数

onCreateViewHolder方法中的parent参数本身持有有效Context,完全不需要在Adapter构造中额外传递Context,这是更简洁的实现方式:

// 移除Context参数,同时明确泛型类型
class AdapterItem(val userList: List<MyDataItem>) : RecyclerView.Adapter<AdapterItem.ViewHolder>() {

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        // 简化变量初始化
        val numeLista: TextView = itemView.numeLista
        val caloriiLista: TextView = itemView.caloriiLista
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // 使用parent.context获取LayoutInflater
        val itemView = LayoutInflater.from(parent.context)
            .inflate(R.layout.row_items, parent, false)
        return ViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = userList[position]
        holder.numeLista.text = item.foodItems[0].foodName
        holder.caloriiLista.text = item.foodItems[0].calories.toString()
    }

    override fun getItemCount(): Int = userList.size
}

此时Fragment中实例化Adapter时无需传递Context:

// 在onResponse回调中
response.body()?.let { dataList ->
    adapterItem = AdapterItem(dataList)
    binding?.recyclerview_lista?.adapter = adapterItem
}

方案2:保留原Adapter结构,传递安全的Context

如果必须保留Adapter构造中的Context参数,可在Fragment中使用以下两种安全方式获取Context:

  • requireContext():Fragment附着在Activity上时返回非空Context,未附着时抛出异常,适合确定Fragment处于活跃状态的场景
  • view.context:需确保view已初始化(例如在onViewCreated之后调用接口)

同时修复原Fragment中的空指针问题,修改后的关键代码:

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val fragmentBinding = FragmentInformationBinding.inflate(inflater, container, false)
    binding = fragmentBinding
    // 先初始化binding再操作RecyclerView
    binding?.recyclerview_lista?.apply {
        setHasFixedSize(true)
        layoutManager = LinearLayoutManager(context)
    }
    getMyData()
    return fragmentBinding.root
}

private fun getMyData() {
    // ... Retrofit初始化代码不变
    retrofitData.enqueue(object : Callback<List<MyDataItem>?> {
        override fun onResponse(
            call: Call<List<MyDataItem>?>,
            response: Response<List<MyDataItem>?>
        ) {
            response.body()?.let { dataList ->
                // 使用requireContext()传递安全的Context
                adapterItem = AdapterItem(requireContext(), dataList)
                binding?.recyclerview_lista?.adapter = adapterItem
                // 刚设置Adapter时会自动刷新,无需调用notifyDataSetChanged
            }
        }

        // ... onFailure代码不变
    })
}

额外注意事项

  1. 避免使用this.context,它可能为空,优先选择requireContext()或view.context
  2. Retrofit回调是异步的,可通过viewLifecycleOwner.lifecycle.currentState判断Fragment是否活跃,防止内存泄漏
  3. 必须先初始化ViewBinding,再操作其中的控件,避免空指针异常

内容的提问来源于stack exchange,提问作者Vlad Duta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:48:04