1. 前言

最近我在项目中,发现一个同事写 RecyclerView.Adapter 的时候都习惯定义一个全局的私有 mContext,然后在onCreateViewHolder(parent: ViewGroup, viewType: Int) 方法中进行赋值操作 mContext = parent.context

如下:

class MyAdapter(private val dataList: List<MyData>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {private lateinit var mContext: Contextoverride fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {//在这里进行context的赋值mContext = parent.contextval view = LayoutInflater.from(parent.context).inflate(R.layout.rcy_item_view, parent, false)return MyViewHolder(view)}override fun getItemCount(): Int {}override fun onBindViewHolder(holder: MyViewHolder, position: Int) {}
}

WT,还可以这么操作!!第一次见到这样的写法,有点意思,由此有了这一篇文章。

2. 获取到 Context 的四种方式

很多时候我们需要在 RecyclerView.Adapter 中使用到 context,比如:利用 Glide 来加载网络图片的时候。

这时,我们该如何拿到 context 给 Glide 呢?

2.1 通过 Adapter 构造函数传入 Context

这是我之前最常用的一种方式,通过 Adapter 构造函数将当前Activity Context传进来,如下:

class MyAdapter(private val context: Context,private val dataList: List<MyData>
) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {class MyViewHolder(val binding: RcyItemViewBinding) :RecyclerView.ViewHolder(binding.root) {}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val binding = RcyItemViewBinding.inflate(LayoutInflater.from(parent.context),parent,false)return MyViewHolder(binding)}override fun getItemCount(): Int = dataList.sizeoverride fun onBindViewHolder(holder: MyViewHolder, position: Int) {val data = dataList[position]holder.binding.apply {Glide.with(context).load(data.imageUrl).into(holder.binding.imageIv)holder.binding.contentTv.text = data.content}}
}

2.2 通过 Parent.context 获取

这个也是文章开头中提到的我的同事的一种写法,如下:

class MyAdapter(private val dataList: List<MyData>) :RecyclerView.Adapter<MyAdapter.MyViewHolder>() {private lateinit var mContext: Contextclass MyViewHolder(val binding: RcyItemViewBinding) :RecyclerView.ViewHolder(binding.root) {}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {mContext = parent.contextval binding = RcyItemViewBinding.inflate(LayoutInflater.from(parent.context),parent,false)return MyViewHolder(binding)}override fun getItemCount(): Int = dataList.sizeoverride fun onBindViewHolder(holder: MyViewHolder, position: Int) {val data = dataList[position]holder.binding.apply {Glide.with(mContext).load(data.imageUrl).into(holder.binding.imageIv)holder.binding.contentTv.text = data.content}}
}

2.3 通过 onAttachedToRecyclerView() 方法获取

对于2.2 的方法,通过 parent.context 对 mContext 进行赋值,有人说,不可以这么操作!这样会导致内存泄露!!(留个疑问?你觉得2.2方法这样操作会导致内存泄漏吗?
所以你需要覆写 onAttachedToRecyclerView(recyclerView: RecyclerView) 方法,在这里对 mContext 进行赋值。如下:

class MyAdapter(private val dataList: List<MyData>) :RecyclerView.Adapter<MyAdapter.MyViewHolder>() {private lateinit var mContext: Contextoverride fun onAttachedToRecyclerView(recyclerView: RecyclerView) {super.onAttachedToRecyclerView(recyclerView)mContext = recyclerView.context}class MyViewHolder(val binding: RcyItemViewBinding) :RecyclerView.ViewHolder(binding.root) {}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val binding = RcyItemViewBinding.inflate(LayoutInflater.from(parent.context),parent,false)return MyViewHolder(binding)}override fun getItemCount(): Int = dataList.sizeoverride fun onBindViewHolder(holder: MyViewHolder, position: Int) {val data = dataList[position]holder.binding.apply {Glide.with(mContext).load(data.imageUrl).into(holder.binding.imageIv)holder.binding.contentTv.text = data.content}}
}

2.4 通过 ImageView 获取 context

当当就我们举的这个例子,因为我们需要用到 Glide 来展示网络图片,所以我们需要传递 Context 给 Glide,其实我们可以直接通过 ImageView 来拿到 context,然后传给 Glide,如下:

class MyAdapter(private val dataList: List<MyData>) :RecyclerView.Adapter<MyAdapter.MyViewHolder>() {class MyViewHolder(val binding: RcyItemViewBinding) :RecyclerView.ViewHolder(binding.root) {}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val binding = RcyItemViewBinding.inflate(LayoutInflater.from(parent.context),parent,false)return MyViewHolder(binding)}override fun getItemCount(): Int = dataList.sizeoverride fun onBindViewHolder(holder: MyViewHolder, position: Int) {val data = dataList[position]holder.binding.apply {Glide.with(imageIv.context).load(data.imageUrl).into(holder.binding.imageIv)holder.binding.contentTv.text = data.content}}
}

3. 问题的本质

上面介绍了四种方法来获取 Context,想必大家都想弄清楚上面几种方法有什么区别吧,那我们就打印他们获取到的 context 出来瞧瞧看吧,如下:

class MainActivity : AppCompatActivity() {private lateinit var binding: ActivityMainBinding···override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)Log.e("jctest", "onCreate: this::class.java = ${this::class.java}")Log.e("jctest", "onCreate: binding.recyclerView.context::class.java = ${binding.recyclerView.context::class.java}")val adapter = MyAdapter(listData)binding.recyclerView.adapter = adapter}class MyAdapter(private val dataList: List<MyData>) :RecyclerView.Adapter<MyAdapter.MyViewHolder>() {class MyViewHolder(val binding: RcyItemViewBinding) :RecyclerView.ViewHolder(binding.root) {}override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {Log.e("jctest", "onCreateViewHolder: parent::class.java = ${parent::class.java}")Log.e("jctest", "onCreateViewHolder: parent.context::class.java = ${parent.context::class.java}")val binding = RcyItemViewBinding.inflate(LayoutInflater.from(parent.context),parent,false)return MyViewHolder(binding)}override fun getItemCount(): Int = dataList.sizeoverride fun onBindViewHolder(holder: MyViewHolder, position: Int) {val data = dataList[position]holder.binding.apply {Log.e("jctest", "onBindViewHolder: imageIv.context::class.java = ${imageIv.context::class.java}")Glide.with(imageIv.context).load(data.imageUrl).into(holder.binding.imageIv)holder.binding.contentTv.text = data.content}}override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {super.onAttachedToRecyclerView(recyclerView)Log.e("jctest", "onAttachedToRecyclerView: recyclerView.context::class.java = ${recyclerView.context::class.java}")}}}

打印出来的 Log 如下:

E/jctest: onCreate: this::class.java = class com.jc.test.MainActivity
E/jctest: onCreate: binding.recyclerView.context::class.java = class com.jc.test.MainActivity
E/jctest: onAttachedToRecyclerView: recyclerView.context::class.java = class com.jc.test.MainActivity
E/jctest: onCreateViewHolder: parent::class.java = class androidx.recyclerview.widget.RecyclerView
E/jctest: onCreateViewHolder: parent.context::class.java = class com.jc.test.MainActivity
E/jctest: onBindViewHolder: imageIv.context::class.java = class com.jc.test.MainActivity

通过 Log,真的就一目了然了,这四种方法虽然看着写法很不一样,但是其获取到的 context 其实都是同一个,那就是 MainActivity。

我们再来看看这四个方法:

  • 2.1 通过 Adapter 构造函数传入 this,这很明显,就是 MainActivity。
  • 2.2 通过 Parent.context 获取,通过 Log 我们可以知道,parent 就是 recylerView,所以获取的是 recyclerView 运行于的上下文,也就是 MainActivity。
  • 2.3 通过 onAttachedToRecyclerView() 获取,也是获取 recyclerView 运行于的上下文,即 MainActivity。
  • 2.4 通过 ImageView 获取,获取的是 ImageView 运行于的上下文,ImageView 是运行于 recyclerView 上的,所以获取的也是 MainActivity。

3.1 到底应该怎么用呢?

刚刚,我们通过打印 Log 知道了这四种方法获取到的 Context 其实都是同一个,那~~,这四种方法又该如何来取舍呢?到底用哪一种方法比较好呢?

文章开头中,我说 2.1 是我之前最常用的一个方法,那我现在为什么不用它了呢??

原因很简单,那就是因为之前我不知道可以直接在 Adapter 内部直接获取到 Context

如何在Adapter中正确的使用Context相关推荐

  1. jest.conf.js_如何在Jest中正确模拟Moment.js / dates

    jest.conf.js by Iain Nash 由伊恩·纳什(Iain Nash) 如何在Jest中正确模拟Moment.js / dates (How to correctly mock Mom ...

  2. 如何在R中正确使用列表?

    本文翻译自:How to Correctly Use Lists in R? Brief background: Many (most?) contemporary programming langu ...

  3. css中 media的用法,如何在css中正确使用@media

    如何在css中使用@media作为特定分辨率?所以我想让我的侧栏更改取决于用户分辨率,所以我使用@media.如何在css中正确使用@media 这是示例代码: @media (max-width: ...

  4. java 中覆 写tostring_如何在Java中正确覆盖toString()?

    如何在Java中正确覆盖toString()? 听起来有点愚蠢,但我需要帮助我的toString()方法,这是非常irking. 我尝试在网上查找,因为toString是搞砸了,"没有找到K ...

  5. MySQL中使用CASE出错,如何在MySQL中正确使用CASE..WHEN

    如何在MySQL中正确使用CASE..WHEN 这里是一个演示查询,注意它非常简单,仅在base_price为0的位置获取,并且仍然select条件3: SELECT CASE course_enro ...

  6. python异步加载图片_如何在PyQt5中正确异步加载图像?

    我在尝试如何在pyqtqlistview中正确地完成异步映像加载.在 我的主小部件由一个Qlistview和一个QLineEdit文本框组成. 我有一个参与者数据库,我使用QAbstractListM ...

  7. scarpy框架如何在crawl中正确传递自定义参数,scrapy.cmdline的execute为什么不能在while True中无限循环,execute换成crawl 方法

    问题:scrapy.cmdline的execute函数执行完毕为什么一定会停,不能执行后面函数,也不在while True中无限循环(解决问题的结果 在最后) 我想让scrapy程序全年无休止运行,2 ...

  8. html界面出现 section,如何在HTML5中正确使用“ section”标签?

    标记的正确方法是什么? 从技术上讲,两者都是正确的. 我要说的是,这两个示例看起来都不正确--但是很难用纯文本而不是真实上下文来说明,因为是语义标记,而不是像这样的通用包装. 您当然不应该有两个具有相 ...

  9. 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. wait, notify 和 noti ...

最新文章

  1. jquery checkbox勾选/取消勾选的诡异问题
  2. 《Hadoop MapReduce性能优化》一1.3 Hadoop MapReduce的工作原理
  3. 2019ICPC(南昌) - The Nth Item(矩阵快速幂)
  4. 音视频技术开发周刊 | 199
  5. 解决android studio引用远程仓库下载慢(JCenter下载慢)
  6. java 抽象类 final_final/抽象类/interface
  7. 1.请求安全-- MD5的必要性以及实际应用场景
  8. Maven依赖junit @Test报错解决
  9. 有个做微商的兄弟,他是卖品牌运动鞋的,最近很苦恼
  10. WannaCry反思:传统安全理念遭遇马奇诺防线式溃败
  11. 【转】简明 Python 教程
  12. 《罗辑思维》让知识交融做爱
  13. matlab 发动机万有特性,用MATLAB语言绘制发动机万有特性的两种方法
  14. hbase 查询固定条数_HBase统计表行数(RowCount)的四种方法
  15. 局域网远程控制工具之VNC
  16. c语言自动插桩,01 - LLVM Pass 实现 C函数 插桩
  17. 数字图像处理,相位相关算法解决图像的刚性平移问题
  18. 【STM32学习】(28)STM32实现光照度采集(标准库和HAL库实现)
  19. Redis(三)【五大数据类型三种特殊数据类型】
  20. java格式化XML文件

热门文章

  1. localhost 已拒绝连接(命令窗口安装版)还有安装教程
  2. mayavi实现kitti数据集可视化
  3. PigGo-安装及使用
  4. 夕食の後のレギュラーエクスプレスについての議論(1)
  5. 用户不小心忘记了密码,造成无法登录Windows2000 时怎么办?
  6. 计算机三级考试嵌入式系统重点精简汇总
  7. 西北工业大学与华为联合研发的首个面向飞行器的流体力学大模型“秦岭·翱翔”预发布
  8. sv中packed struct
  9. c语言while else语句用法,C语言注释C语言的主要功能else语句,while语句,dowhile语句,sw...
  10. 机器学习实战-57: 人工神经网络分类算法(Artificial Neural Network)