关于view.context引发的思考

今天在复习Glide的原理,然后就顺道过了一遍项目中的封装Glide工具类,看到了有个别方法为了不传入context类型的参数进来,直接通过这种方式:

Glide.with(view.context)

而检查了Glide的源码,看到只有以下的方法

 Glide.with(Context context);// 绑定Context
 Glide.with(Activity activity);// 绑定Activity
 Glide.with(FragmentActivity activity);// 绑定FragmentActivity
 Glide.with(Fragment fragment);// 绑定Fragment

但是需要注意的是with()方法中传入的实例会决定Glide加载图片的生命周期,如果传入的是Activity、Fragment或者FragmentActivity的实例,
那么当其被销毁时图片加载也会停止,如果传入的是ApplicationContext时只有当应用程序被杀掉的时候图片加载才会停止。

于是就想知道,以上的写法,是否拿到的就是Activity呢?

查了一下:

  /**
     * Returns the context the view is running in, through which it can
     * access the current theme, resources, etc.
     *
     * @return The view's Context.
     */
    @ViewDebug.CapturedViewProperty
    public final Context getContext() {
        return mContext;
    }
  1. View中的Context是View正在运行的上下文环境中,并且可以通过Context获取资源和主题等。根据这些信息我们可以判断View中的Context是一个ContextThemeWrapper类型的Context。
public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

  1. 看代码,在Activity的setContentView()方法中View会被创建以及绘制:调用了Window的setContentView()方法,这个Window就是PhoneWindow:
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor(); //首先初始化DecorView
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    //.........
}

  1. 代码中首先初始化了DecorView也就是顶级View,在DecorView创建完成后,接下来就是生成布局。这里就开始了View的初始化过程。
  2. 再一步步下来,会在inflate方法中,调用到createViewFromTag方法来创建 View。View的context也在这里被创建出来。
View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
            boolean ignoreThemeAttr) {
        if (name.equals("view")) {
            name = attrs.getAttributeValue(null, "class");
        }

        // Apply a theme wrapper, if allowed and one is specified.
        if (!ignoreThemeAttr) {
            //这里为View创建了一个ContextThemeWrapper类型的Context
            final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
            final int themeResId = ta.getResourceId(0, 0);
            if (themeResId != 0) {
                context = new ContextThemeWrapper(context, themeResId);
            }
            ta.recycle();
        }

        if (name.equals(TAG_1995)) {
            // Let's party like it's 1995!
            return new BlinkLayout(context, attrs);
        }
        try {
            View view;
            if (mFactory2 != null) {
                view = mFactory2.onCreateView(parent, name, context, attrs);
            } else if (mFactory != null) {
                view = mFactory.onCreateView(name, context, attrs);
            } else {
                view = null;
            }

            if (view == null && mPrivateFactory != null) {
                view = mPrivateFactory.onCreateView(parent, name, context, attrs);
            }
            if (view == null) {
                final Object lastContext = mConstructorArgs[0];
                mConstructorArgs[0] = context;
                try {
                    if (-1 == name.indexOf('.')) {
                        view = onCreateView(parent, name, attrs);
                    } else {
                        view = createView(name, null, attrs);
                    }
                } finally {
                    mConstructorArgs[0] = lastContext;
                }
            }

            return view;
        } 
    }

综上,View中的Context是ContextThemeWrapper类型的。在View被绘制之前的初始化过程中被创建。
这个LayoutInflater的context是PhoneWindow传进去的,而PhoneWindow的context就是Activity的this。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我要用Intent实现跳转,应该把代码加在哪?package com.example.afinal import android.content.Intent import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import android.view.LayoutInflater import android.widget.Toast class ContextAdapter(val contextList: List<ContextModel>) : RecyclerView.Adapter<ContextAdapter.ViewHolder>() { inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val contextCover: ImageView = view.findViewById(R.id.contextCover) val contextTitle: TextView = view.findViewById(R.id.contextTitle) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.home_context, parent, false) val viewHolder = ViewHolder(view) viewHolder.itemView.setOnClickListener { val position = viewHolder.adapterPosition val conetext = contextList[position] Toast.makeText(parent.context, "you clicked view ${conetext.title}", Toast.LENGTH_SHORT).show() } viewHolder.contextCover.setOnClickListener { val position = viewHolder.adapterPosition val context = contextList[position] Toast.makeText(parent.context, "you clicked image ${context.title}", Toast.LENGTH_SHORT).show() } return viewHolder } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val context = contextList[position] holder.contextCover.setImageResource(context.coverUrl) holder.contextTitle.text = context.title holder.itemView.setOnClickListener { intent=Intent(this,DetailsActivity::class.java) } } override fun getItemCount() = contextList.size }
最新发布
04-23

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值