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,代码结构也更清晰:
- 先修改Activity的布局,把原来的LinearLayout换成RecyclerView:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
- 创建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); } } }
- 在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
相关产品推荐
相关产品推荐

