安卓开发工程师-adapter

在 Android 开发中,Adapter 是连接数据源(如数组、列表、数据库)与 UI 组件(如 ListViewRecyclerViewSpinner)的桥梁。以下从不同角度详细介绍 Adapter 及其 Java 实现。


一、Adapter 的核心概念

  1. 作用
    将数据(如字符串、对象)动态绑定到 UI 组件,每个数据项生成对应的视图(View)。
  2. 核心方法
    getCount(): 返回数据项总数。
    getItem(int position): 返回特定位置的数据项。
    getItemId(int position): 返回数据项的唯一 ID。
    getView(int position, View convertView, ViewGroup parent): 生成数据项对应的视图。

二、常见 Adapter 类型及示例

1. ArrayAdapter

用途:将数组或列表数据绑定到 ListViewSpinner
特点:内置简单布局,支持自定义布局。

// 示例:绑定字符串数组到 ListView
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView listView = findViewById(R.id.list_view);
        String[] data = {"Apple", "Banana", "Cherry"};
        ArrayAdapter<String> adapter = new ArrayAdapter<>(
            this,
            android.R.layout.simple_list_item_1, // 内置布局
            data
        );
        listView.setAdapter(adapter);
    }
}
2. BaseAdapter(自定义 Adapter)

用途:完全自定义列表项布局和逻辑。
关键优化:使用 ViewHolder 减少 findViewById 调用。

// 示例:自定义 Adapter 显示图标和文本
public class CustomAdapter extends BaseAdapter {
    private Context context;
    private List<Item> items;

    public CustomAdapter(Context context, List<Item> items) {
        this.context = context;
        this.items = items;
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public Object getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context)
                .inflate(R.layout.list_item, parent, false);
            holder = new ViewHolder();
            holder.image = convertView.findViewById(R.id.image_view);
            holder.text = convertView.findViewById(R.id.text_view);
            convertView.setTag(holder); // 缓存 ViewHolder
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Item item = items.get(position);
        holder.image.setImageResource(item.getImageResId());
        holder.text.setText(item.getText());
        return convertView;
    }

    static class ViewHolder {
        ImageView image;
        TextView text;
    }
}
3. RecyclerView.Adapter

用途:现代列表组件 RecyclerView 的 Adapter,支持更灵活的布局和动画。
关键特性:强制使用 ViewHolder 模式,分离布局管理器(LayoutManager)和装饰(ItemDecoration)。

// 示例:RecyclerView Adapter
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
    private List<String> data;

    public MyRecyclerAdapter(List<String> data) {
        this.data = data;
    }

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

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.textView.setText(data.get(position));
    }

    @Override
    public int getCount() {
        return data.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.text_view);
        }
    }
}

三、Adapter 的优化技巧

  1. 复用 convertView
    getView() 中复用 convertView 减少视图创建开销。
  2. ViewHolder 模式
    缓存视图组件,避免重复调用 findViewById
  3. 局部更新数据
    使用 notifyItemChanged(int position) 代替 notifyDataSetChanged()(针对 RecyclerView)。

四、高级用法

1. 多布局类型

• 重写 getItemViewType()getViewTypeCount()(对 ListView)或 RecyclerView.AdaptergetItemViewType()

// 示例:RecyclerView 多布局类型
@Override
public int getItemViewType(int position) {
    return (data.get(position).isHeader()) ? TYPE_HEADER : TYPE_ITEM;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (viewType == TYPE_HEADER) {
        // 加载头部布局
    } else {
        // 加载普通项布局
    }
}
2. 点击事件处理

• 在 Adapter 中定义接口回调。

// 示例:定义点击监听器
public interface OnItemClickListener {
    void onItemClick(int position);
}

public class CustomAdapter extends BaseAdapter {
    private OnItemClickListener listener;

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // ...
        convertView.setOnClickListener(v -> {
            if (listener != null) {
                listener.onItemClick(position);
            }
        });
        return convertView;
    }
}

五、Adapter 的生命周期与数据更新

  1. 数据更新
    ArrayAdapter: 修改数据源后调用 notifyDataSetChanged()
    RecyclerView.Adapter: 使用 DiffUtil 高效更新数据。
  2. 内存管理
    • 避免在 Adapter 中持有 ActivityFragment 的引用(防止内存泄漏)。
    • 使用弱引用或传递 ApplicationContext

六、最佳实践

  1. 优先使用 RecyclerView
    替代 ListViewGridView,支持更灵活的布局和动画。
  2. 分离关注点
    将数据操作(如排序、过滤)放在 Adapter 外部。
  3. 使用数据绑定库
    通过 Data BindingView Binding 简化 findViewById 调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值