Android View绘制(一)- LayoutInflater.inflate() 流程简要解析

Android View绘制- LayoutInflater.inflate() 流程简要解析

布局,作为 Android 中展示 UI 的最主要的元素,其实它是怎么通过布局文件转化为实际的 UI 的?这篇文章,就是对这一过程进行简要的解析,并且提出一些实际开发过程需要注意的问题。

阅读该文章你可以了解到

  1. LayoutInfalter 的工作过程
  2. 布局优化的一些建议

LayoutInflater 原理讲解

我们需要在 Activity 上显示一个布局文件,通常在 Activity 的 onCreate() 使用以下代码:

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_inner_class_memory_leack);
}

实际上, setContentView() 的调用链如下

// Activity.setContentView(),这里的getWindow() 拿到的是一个 PhoneWindow 对象
public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}
// PhoneWinwod.setContent()
public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
 }

最终会进入到 PhoneWindow 这里,然后最终调用的代码是第二十二行的 mLayoutInflater.inflate(layoutResID, mContentParent); 这一行代码,这里将 mContentParent 传入作为父容器。然后最终都会调用到 LayoutInflater 的 inflate() 方法,如下:

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    synchronized (mConstructorArgs) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        View result = root;//注意该方法的返回值

        try {
            // Look for the root node.
            int type;
            
package com.zw.camera2test; import android.content.Context; import android.graphics.Bitmap; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.appcompat.widget.LinearLayoutCompat; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.CenterCrop; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; import java.util.List; /** * @author : weizhang39 * @date : 2022/4/18 * @email : weizhang39@iflytek.com * @description : */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { private Context mContext; private List<Bitmap> mList; public MyAdapter(Context mContext, List<Bitmap> mList) { this.mContext = mContext; this.mList = mList; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.item_my,parent,false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { holder.tvName.setText(""+position); Glide.with(mContext).load(mList.get(position)) .apply(new RequestOptions() ).into(holder.imgView); } @Override public int getItemCount() { return mList.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { private ImageView imgView; private TextView tvName; public MyViewHolder(@NonNull View itemView) { super(itemView); tvName = itemView.findViewById(R.id.tvName); imgView = itemView.findViewById(R.id.imgView); }}}d
03-25
package com.lucashu.recyclerview; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { RecyclerView mRecyclerView; MyAdapter mMyAdapter ; List<News> mNewsList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView = findViewById(R.id.recyclerview); // 构造些数据 for (int i = 0; i < 50; i++) { News news = new News(); news.title = "标题" + i; news.content = "内容" + i; mNewsList.add(news); } mMyAdapter = new MyAdapter(); mRecyclerView.setAdapter(mMyAdapter); LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this); mRecyclerView.setLayoutManager(layoutManager); } class MyAdapter extends RecyclerView.Adapter<MyViewHoder> { @NonNull @Override public MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = View.inflate(MainActivity.this, R.layout.item_list, null); MyViewHoder myViewHoder = new MyViewHoder(view); return myViewHoder; } @Override public void onBindViewHolder(@NonNull MyViewHoder holder, int position) { News news = mNewsList.get(position); holder.mTitleTv.setText(news.title); holder.mTitleContent.setText(news.content); } @Override public int getItemCount() { return mNewsList.size(); } } class MyViewHoder extends RecyclerView.ViewHolder { TextView mTitleTv; TextView mTitleContent; public MyViewHoder(@NonNull View itemView) { super(itemView); mTitleTv = itemView.findViewById(R.id.textView); mTitleContent = itemView.findViewById(R.id.textView2); } } }
最新发布
08-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值