📜  android listview 到 recyclerview (1)

📅  最后修改于: 2023-12-03 15:13:20.429000             🧑  作者: Mango

从Android ListView迁移到RecyclerView

简介

ListView 是 Android 开发中使用非常广泛的组件。然而,随着许多新的功能(如动画、复杂布局等)的要求,ListView 已经不足以满足我们的需求。为了应对这些问题,Google 推出了一个新的组件:RecyclerView。

RecyclerView 与 ListView 相似,但具有更好的性能和更丰富的功能。它是一种更高级别的、强大的实现,可用于实现更复杂的布局和动画。

在这篇文章中,我们将讨论如何将你的 ListView 迁移到 RecyclerView 中。

步骤
步骤一:导入 RecyclerView 库

要开始使用 RecyclerView,需要在 build.gradle 文件中添加 RecyclerView 依赖项:

implementation 'androidx.recyclerview:recyclerview:{version}'
步骤二:更改布局文件

一旦库已经导入,我们就需要修改布局文件来替换 ListView。图片描述

要进行此操作,我们可以使用 RecyclerView 标签替换现有的 ListView 标签:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
步骤三:更改代码

现在我们已经将布局文件迁移到 RecyclerView 中,我们需要修改 Java 代码来更新 Adapter 和 ViewHolder。以下是在 ListView 和 RecyclerView 中使用的标准流程:

1. 创建 ViewHolder

在 RecyclerView 中,不再需要 ViewHolder 中的 findViewById()。相反,它是由构造函数注入的。然而,因为 RecyclerView 根据需要复用 ViewHolder,所以它可能处于多个布局中,因此我们需要在 ViewHolder 的构造函数中为它提供合适的视图类型。

ViewHolder 代码在 ListView 和 RecyclerView 中稍有不同:

ListView 的 ViewHolder:

public static class ViewHolder {
    public TextView textView;
    public ViewHolder(View itemView) {
        textView = (TextView)itemView.findViewById(R.id.text);
    }
}

RecyclerView 的 ViewHolder:

public class ViewHolder extends RecyclerView.ViewHolder {
    public TextView textView;
    public ViewHolder(View itemView) {
        super(itemView);
        textView = (TextView)itemView.findViewById(R.id.text);
    }
}

可以看到,在 RecyclerView 中,我们的 ViewHolder 扩展了 RecyclerView.ViewHolder 并在构造函数中调用了 super()。这确保了它拥有与 RecyclerView 相关的功能。

2. 创建 Adapter

RecyclerView 的 Adapter 需要我们实现一个新的方法:onBindViewHolder()。此方法与 getView() 方法类似,但它将 ViewHolder 作为参数,而不是返回一个。

ListAdapter 代码:

public class ListAdapter extends ArrayAdapter<String> {
    private final LayoutInflater mInflater;
    private final List<String> mItems;

    public ListAdapter(Context context, List<String> items) {
        super(context, R.layout.list_item, items);
        mInflater = LayoutInflater.from(context);
        mItems = items;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.list_item, parent, false);
            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.textView.setText(getItem(position));

        return convertView;
    }

    private static class ViewHolder {
        public TextView textView;

        public ViewHolder(View itemView) {
            textView = (TextView)itemView.findViewById(R.id.text);
        }
    }
}

RecyclerView 的 Adapter 代码:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
    private List<String> mItems;
    private LayoutInflater mInflater;

    public RecyclerViewAdapter(Context context, List<String> data) {
        this.mInflater = LayoutInflater.from(context);
        this.mItems = data;
    }
    
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.list_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String item = mItems.get(position);
        holder.textView.setText(item);
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

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

与我们在 ListView 中使用的 Adapter 不同,RecyclerViewAdapter 扩展了 RecyclerView.Adapter,其中 T 表示 ViewHolder。我们指定了自己实现的 ViewHolder,这是我们在第一步中创建的类。

在 onBindViewHolder() 方法中,我们更新 ViewHolder 中的数据。它非常类似于 getView(),除了我们需要将数据直接注入ViewHolder。

3. 更新 Activity/Fragment

要在 RecyclerView 中使用 Adapter,我们需要像 ListView 一样检索 RecyclerView,并设置它的 Adapter。 RecyclerView 也需要设置一个 LayoutManager 来控制它的布局,否则会难以处理元素的位置。

以上为 ListView 代码:

public class MainActivity extends Activity {
    private ListView mListView;
    private ListAdapter mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.list);

        mAdapter = new ListAdapter(this, generateItemsList());
        mListView.setAdapter(mAdapter);
    }

    private List<String> generateItemsList() {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 1000; ++i) {
            list.add("Item " + i);
        }
        return list;
    }
}

以下为 RecyclerView 代码:

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private RecyclerViewAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = findViewById(R.id.recyclerview);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        mAdapter = new RecyclerViewAdapter(this, generateItemsList());
        mRecyclerView.setAdapter(mAdapter);
    }

    private List<String> generateItemsList() {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 1000; ++i) {
            list.add("Item " + i);
        }
        return list;
    }
}

在以上代码中,我们使用 mRecyclerView.setLayoutManager() 方法设置了一个 LinearLayoutManager,这是官方提供的一个特定的 LayoutManager。 RecyclerView 可以使用其他类型的LayoutManager(如 GridLayoutManager 或 StaggeredGridLayoutManager),这取决于你的需求。

结论

现在你已经可以使用 RecyclerView 了! 这不仅提高了性能,而且还提供了更多选择。希望这篇文章能帮助你迁移你的 ListView 到 RecyclerView,并成功地开始使用这个更高级别的组件。