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

Android代码优化:复用布局创建TextView及实现点击事件

优化方案详解

没问题,我来帮你一步步实现TextView样式复用和点击事件的优化:


第一步:创建自定义TextView布局文件

先把重复的样式属性提取到单独的布局文件中,这样既符合Android布局与逻辑分离的原则,又能避免代码重复。创建res/layout/style_textview.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_item" <!-- 给TextView设置唯一id,方便后续引用 -->
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:textColor="#4682B4"
    android:textSize="21sp"
    android:padding="8dp"
    android:text="@string/t1" /> <!-- 如果文本固定的话可以直接写在这里,动态修改的话再在代码里设置 -->

第二步:在循环中加载自定义布局并添加到容器

这里要注意正确使用LayoutInflater,传入父布局可以让TextView自动继承父布局的LayoutParams,不需要手动创建LinearLayout.LayoutParams。修改后的Activity代码:

public class CreateListActivity extends AppCompatActivity implements View.OnClickListener {
    private int[] textViewIds; // 用来保存每个TextView的id,方便点击事件判断

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_list);
        LinearLayout myLayout = findViewById(R.id.llContainer2);
        int textViewCount = 24;
        textViewIds = new int[textViewCount];
        LayoutInflater inflater = getLayoutInflater();

        for(int i = 0; i < textViewCount; i++) {
            // 加载布局时传入父布局myLayout,第三个参数false表示暂时不自动添加到父布局
            TextView textView = (TextView) inflater.inflate(R.layout.style_textview, myLayout, false);
            
            // 设置唯一id:API 17+用View.generateViewId(),低版本可以在values/ids.xml预先定义
            int viewId = View.generateViewId();
            textView.setId(viewId);
            textViewIds[i] = viewId;
            
            // 如果需要动态修改文本,在这里设置(xml里已经写了的话可以省略)
            // textView.setText(getString(R.string.t1));
            
            textView.setOnClickListener(this);
            myLayout.addView(textView);
        }
    }

    // ... 点击事件实现见第三步
}

第三步:实现点击事件逻辑

因为我们是动态生成的id,直接用switch(v.getId())会不方便,推荐用数组保存id并匹配位置的方式,灵活且易维护:

@Override
public void onClick(View v) {
    int clickedId = v.getId();
    for(int i = 0; i < textViewIds.length; i++) {
        if(clickedId == textViewIds[i]) {
            // 根据点击的位置i处理逻辑,比如启动对应的Activity
            switch(i) {
                case 0:
                    // 第一个TextView被点击,启动Activity A
                    startActivity(new Intent(this, ActivityA.class));
                    break;
                case 1:
                    // 第二个TextView被点击,启动Activity B
                    startActivity(new Intent(this, ActivityB.class));
                    break;
                // ... 其他位置的处理逻辑
            }
            break;
        }
    }
}

如果你的项目需要兼容API 17以下的版本,可以在res/values/ids.xml预先定义一组id:

<resources>
    <item type="id" name="tv_0"/>
    <item type="id" name="tv_1"/>
    <!-- ... 一直定义到tv_23 -->
</resources>

然后在循环中设置id:

textView.setId(getResources().getIdentifier("tv_" + i, "id", getPackageName()));

此时点击事件可以直接用switch匹配预设的id:

@Override
public void onClick(View v) {
    switch (v.getId()){
        case R.id.tv_0:
            startActivity(new Intent(this, ActivityA.class));
            break;
        case R.id.tv_1:
            startActivity(new Intent(this, ActivityB.class));
            break;
        // ... 其他case
    }
}

更优解决方案:用RecyclerView替代手动添加

如果你的场景是创建列表类的视图,RecyclerView是更好的选择,它自带视图复用机制,性能远优于LinearLayout手动添加大量View,代码结构也更清晰:

  1. 先修改Activity的布局,把原来的LinearLayout换成RecyclerView:
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  1. 创建RecyclerView的Adapter:
public class TextViewAdapter extends RecyclerView.Adapter<TextViewAdapter.ViewHolder> {
    private Context mContext;
    private int mItemCount;

    public TextViewAdapter(Context context, int itemCount) {
        mContext = context;
        mItemCount = itemCount;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.style_textview, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // 动态设置文本(如果需要的话)
        holder.tvItem.setText(mContext.getString(R.string.t1));
        
        // 设置点击事件
        holder.tvItem.setOnClickListener(v -> {
            // 根据position处理逻辑
            switch(position) {
                case 0:
                    mContext.startActivity(new Intent(mContext, ActivityA.class));
                    break;
                case 1:
                    mContext.startActivity(new Intent(mContext, ActivityB.class));
                    break;
                // ... 其他位置的处理
            }
        });
    }

    @Override
    public int getItemCount() {
        return mItemCount;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView tvItem;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            tvItem = itemView.findViewById(R.id.tv_item);
        }
    }
}
  1. 在Activity中初始化RecyclerView:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_create_list);
    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    // 设置布局管理器,这里用线性布局(和原来的LinearLayout效果一致)
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    // 设置Adapter
    TextViewAdapter adapter = new TextViewAdapter(this, 24);
    recyclerView.setAdapter(adapter);
}

RecyclerView的优势在于:

  • 视图复用,不会一次性创建所有24个TextView,节省内存
  • 自带滑动优化,体验更好
  • 代码结构更清晰,后续扩展功能(比如添加分割线、下拉刷新)更方便

内容的提问来源于stack exchange,提问作者Tony Ming

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:08:21