Java 如何在 RecyclerView 中显示 ArrayList?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37786796/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:41:05  来源:igfitidea点击:

How to display an ArrayList in a RecyclerView?

javaandroidarraylistandroid-recyclerviewandroid-adapter

提问by FET

I need to add an Activitywhere I can list the elements of an ArrayList<CustomClass>and I've seen there's a newer and better way to display lists - RecyclerView.

我需要添加一个Activity可以列出 an 元素的位置,ArrayList<CustomClass>并且我已经看到有一种更新更好的方式来显示列表 - RecyclerView

My question is how to implement this into my app. I've found that I need to use an Adapter, but I don't quite understand how to implement the whole process correctly.

我的问题是如何将其实现到我的应用程序中。我发现我需要使用Adapter,但我不太明白如何正确实现整个过程。

If you're wondering, I'm referring to thisexamples of the docs, which I have been reading.

如果你想知道,我指的是这个的文档的例子,这是我一直在读。

EDIT:

编辑:

After having updated my code, it says it cannot resolve the symbol setOnEntryClickListener:

更新我的代码后,它说它无法解析符号setOnEntryClickListener

public class voting extends Activity {


RecyclerView myList;
private ArrayList<Player> players; // Players


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

    Intent intent = this.getIntent();
    Bundle bundle = intent.getExtras();
    players = (ArrayList<Player>)bundle.getSerializable("PLAYERS");

    myList = (RecyclerView) findViewById(R.id.charactersList);
    myList.setLayoutManager(new LinearLayoutManager(this));
    CoursesAdapter adapter = new CoursesAdapter(players);
    myList.setAdapter(adapter);
}

// OR RecyclerView with a click listener

CoursesAdapter clickAdapter = new CoursesAdapter(players);
clickAdapter.setOnEntryClickListener(new CoursesAdapter.OnEntryClickListener() {
    @Override
    public void onEntryClick(View view, int position) {
        // stuff that will happen when a list item is clicked
    }
});
recyclerView.setAdapter(clickAdapter);
}

So I've thought I had put that interfacein the wrong place (very probably), infact I've put it in the Adapter class, at the end of it, right after the onAttachedToRecyclerView()Method:

所以我认为我把它interface放在了错误的地方(很可能),事实上我已经把它放在了 Adapter 类中,在它的末尾,就在onAttachedToRecyclerView()Method 之后:

    @Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}


private OnEntryClickListener mOnEntryClickListener;

public interface OnEntryClickListener {
    void onEntryClick(View view, int position);
}

public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
    mOnEntryClickListener = onEntryClickListener;
}



}

采纳答案by Farbod Salamat-Zadeh

I remember when I was first reading about RecyclerViews - I agree it can be a little confusing at first. Hopefully, this explanation will help you understand it better.

我记得当我第一次阅读关于RecyclerViews 的内容时 - 我同意一开始可能会有点混乱。希望这个解释能帮助你更好地理解它。



RecyclerView basics

RecyclerView 基础知识

1. Adding the RecyclerView

1.添加 RecyclerView

First you need to add your RecyclerViewto your XML layout. I'm assuming you know how to do this. You also declare it in your Java code:

首先,您需要将您的添加RecyclerView到您的 XML 布局。我假设你知道如何做到这一点。您还可以在 Java 代码中声明它:

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.your_recycler_view);

2. Creating the Adapterand understanding ViewHolder

2. 创造Adapter和理解ViewHolder

Next, you need to create an Adapterfor it. This is a class that implements RecyclerView.Adapter<YourAdapter.YourViewHolder>. I will explain what this means in a minute.

接下来,您需要Adapter为它创建一个。这是一个实现RecyclerView.Adapter<YourAdapter.YourViewHolder>. 我将在一分钟内解释这意味着什么。

I believe it helps to look at an example of an Adapterto understand how it works (e.g. one I createdfor an open-source app). I would also highly recommend looking through a set of Java files I have made as an example on Gist on GitHub:

我相信看一个例子会有助于Adapter理解它是如何工作的(例如,为一个开源应用程序创建的)。我还强烈建议查看我在 GitHub 上的 Gist 上作为示例制作的一组 Java 文件:

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

I will be referencing the example files from the link above in this explanation so you can follow along.

我将在本说明中引用上面链接中的示例文件,以便您可以继续操作。

You can see that the Adapterclass contains an inner class, which is your ViewHolder. Therefore, it needs to extend RecyclerView.ViewHolder.

您可以看到Adapter该类包含一个内部类,即您的ViewHolder. 因此,它需要扩展RecyclerView.ViewHolder.

Inside this ViewHolder, you declare the variables for the layouts that will be used for each list item in your RecyclerView. In the constructor for your ViewHolder, you assign these variables. I'm referring to this part of the code (I'm giving my example below):

在这个里面ViewHolder,你声明了布局的变量,这些变量将用于你的RecyclerView. 在您的 构造函数中ViewHolder,您分配这些变量。我指的是这部分代码(我在下面给出了我的例子):

ExampleViewHolder(View itemView) {
    super(itemView);
    text1 = (TextView) itemView.findViewById(R.id.text1);
    text2 = (TextView) itemView.findViewById(R.id.text2);
}

That's all you need for your ViewHolder(the inner class in your Adapter).

这就是你的ViewHolder(你的内部类Adapter)所需要的。

3. Understanding the Adapter

3. 了解 Adapter

Like most Java objects, you will need to have a constructor some private variables in your Adapterclass. Here are mine:

与大多数 Java 对象一样,您的类中需要有一些私有变量的构造函数Adapter。这是我的:

private ArrayList<CustomClass> mCustomObjects;

public ExampleAdapter(ArrayList<CustomClass> arrayList) {
    mCustomObjects = arrayList;
}

You will need to have your ArrayList<CustomClass>as a constructor parameter so you can pass the list so your Adaptercan use it.

您需要将您的ArrayList<CustomClass>作为构造函数参数,以便您可以传递列表以便您Adapter可以使用它。

If you look at the rest of the Adapterclass, it contains some methods which it overrides from what it extends. Let's have a quick look at what these are:

如果你看看这个Adapter类的其余部分,它包含一些方法,它从它扩展的内容中覆盖。让我们快速看看这些是什么:

  • getItemCount()returns the size of your list.
  • onCreateViewHolder(...)is used to inflate the layout for your list item.
  • onBindViewHolder(...)configures your layouts for the list item (e.g. setting text to a TextView)
  • getItemCount()返回列表的大小。
  • onCreateViewHolder(...)用于扩展列表项的布局。
  • onBindViewHolder(...)为列表项配置您的布局(例如将文本设置为 a TextView

For most cases, getItemCount()will just return the size()of your ArrayList<CustomClass>.

在大多数情况下,getItemCount()只会返回size()您的ArrayList<CustomClass>.

The onCreateViewHolder(...)method generally stays the same too:

onCreateViewHolder(...)方法通常也保持不变:

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

You can see that I am inflating the layout that I will use as my list item (android.R.layout.simple_list_item_2). This layout is built in to Android so I don't need to create it - of course, your can use whatever layout you wish and then modify your Adapterfor widgets that you may be using. The return type of this method will match whatever you named your ViewHolderinner class.

您可以看到我正在夸大我将用作列表项 ( android.R.layout.simple_list_item_2)的布局。此布局内置于 Android 中,因此我不需要创建它 - 当然,您可以使用任何您希望的布局,然后修改您Adapter可能正在使用的小部件。此方法的返回类型将匹配您命名ViewHolder内部类的任何内容。

Now, the interesting bit is in onBindViewHolder(...). You configure your layouts here, so it is completely up to you what you want to do. Here's a template you could use:

现在,有趣的一点在onBindViewHolder(...). 您可以在此处配置布局,因此您想要做什么完全取决于您。这是您可以使用的模板:

@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
    CustomClass object = mCustomObjects.get(position);

    String firstText = object.getFirstText()
    String secondText = object.getSecondText()

    holder.text1.setText(firstText);
    holder.text2.setText(secondText);
}

Basically, you access your ViewHoldervariables (for the widgets in your list item layout) by doing holder.myWidget. The holderpart is coming from the parameter, which is your ViewHolderwe talked about earlier, and myWidgetwould be the name of the Viewvariable from that.

基本上,您可以ViewHolder通过执行holder.myWidget. 该holder部分来自参数,这是ViewHolder我们之前讨论过的参数,并且是来自该参数myWidgetView变量的名称。

In the example above, the objecthas a getFirstText()method, and the ViewHoldercontains a TextView(text1), so I am setting the text.

在上面的例子中,object有一个getFirstText()方法,并且ViewHolder包含一个TextView( text1),所以我正在设置文本。

There is also one more method - onAttachedToRecyclerView(...). You can use this for more complex things, but at a basic level, it is usually this:

还有一种方法 - onAttachedToRecyclerView(...). 您可以将其用于更复杂的事情,但在基本层面上,通常是这样的:

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

4. Configuring RecyclerView

4. 配置 RecyclerView

Remember at the beginning, when we declared and assigned our RecyclerView?:

还记得一开始,当我们声明并分配我们的RecyclerView? 时:

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.your_recycler_view);

Now we are going to configure it.

现在我们要配置它。

You start by setting a "layout manager". This determines how each list item will be displayed on screen. The common ones are LinearLayoutManagerand GridLayoutManager. The former puts your list items into a standard list (nothing special really, but it is very useful), and the latter organises your list items into a grid type of layout.

您首先设置一个“布局管理器”。这决定了每个列表项在屏幕上的显示方式。常见的是LinearLayoutManagerGridLayoutManager。前者将您的列表项放入标准列表中(实际上没什么特别的,但它非常有用),后者将您的列表项组织成网格类型的布局。

In our example, we're going to use a LinearLayoutManager. To set this on the RecyclerView, we do this:

在我们的示例中,我们将使用LinearLayoutManager. 要在 上设置它RecyclerView,我们这样做:

recyclerView.setLayoutManager(new LinearLayoutManager(this));

That's all.

就这样。

And all we have to do next is to set the Adapterclass we created and customised earlier to your RecyclerView:

我们接下来要做的就是将Adapter我们之前创建和自定义的类设置为您的RecyclerView

ExampleAdapter adapter = new ExampleAdapter(yourCustomArrayList);
recyclerView.setAdapter(adapter);

In the above, I'm assuming your adapteronly has one parameter, but this will depend on how you configured it earlier.

在上面,我假设您adapter只有一个参数,但这取决于您之前的配置方式。

5. Using your RecyclerView

5. 使用您的 RecyclerView

The steps above should give you a working RecyclerView. If you get stuck, you can look at how I added one into my app here.

上面的步骤应该会给你一个工作RecyclerView。如果您遇到问题,你可以看看我如何添加一个到我的应用程序在这里

You can also look through the Google samples for the RecyclerViewimplementation.

您还可以查看Google 示例以了解RecyclerView实现

I hope all of this gave you a clear idea about how RecyclerViewworks.

我希望所有这些都让您对RecyclerView工作原理有一个清晰的了解。



Adding a click listener

添加点击监听器

You may want to add a click listener so that you are not using the RecyclerViewjust for displaying items.

您可能想要添加一个点击侦听器,以便您不使用RecyclerViewjust 来显示项目。

To do this, your inner ViewHolderclass needs to implement View.OnClickListener. This is because you will set an OnClickListenerto the itemViewparameter of the ViewHolder's constructor. Let me show you what I mean:

为此,您的内部ViewHolder类需要实现View.OnClickListener. 这是因为您将 设置为的构造函数OnClickListeneritemView参数ViewHolder。让我告诉你我的意思:

public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView text1, text2;

    ExampleClickViewHolder(View itemView) {
        super(itemView);

        // we do this because we want to check when an item has been clicked:
        itemView.setOnClickListener(this);

        // now, like before, we assign our View variables
        title = (TextView) itemView.findViewById(R.id.text1);
        subtitle = (TextView) itemView.findViewById(R.id.text2);
    }

    @Override
    public void onClick(View v) {
        // The user may not set a click listener for list items, in which case our listener
        // will be null, so we need to check for this
        if (mOnEntryClickListener != null) {
            mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
        }
    }
}

The only other things you need to add are a custom interface for your Adapterand a setter method:

您需要添加的唯一其他内容是您Adapter和 setter 方法的自定义接口:

private OnEntryClickListener mOnEntryClickListener;

public interface OnEntryClickListener {
    void onEntryClick(View view, int position);
}

public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
    mOnEntryClickListener = onEntryClickListener;
}

So your new, click-supporting Adapteris complete.

这样您的新点击支持Adapter就完成了。

Now, let's use it...

现在,让我们使用它...

ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
    @Override
    public void onEntryClick(View view, int position) {
        // stuff that will happen when a list item is clicked
    }
});
recyclerView.setAdapter(clickAdapter);

It's basically how you would set up a normal Adapter, except that you use your setter method that you created to control what you will do when your user clicks a particular list item.

这基本上是您设置普通 的方式Adapter,除了您使用您创建的 setter 方法来控制当您的用户单击特定列表项时您将执行的操作。



To reiterate, you can look through a set of examples I made on this Gist on GitHub:

重申一下,您可以查看我在 GitHub 上的 Gist 上制作的一组示例:

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07

回答by Neo

Here is a working example, hope it will help you :

这是一个工作示例,希望对您有所帮助:

public class BankListAdapter extends RecyclerView.Adapter<BankListAdapter.BankListViewHolder> {

    ArrayList<BankListModel> bankListModels;
    FragmentActivity activity;
    View selectBank;

    public BankListAdapter(ArrayList<BankListModel> bankListModels, FragmentActivity activity) {
        this.bankListModels=bankListModels;
        this.activity=activity;
    }


    @Override
    public BankListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View bankListLayout = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bank_list, null);
        BankListViewHolder bankListViewHolder = new BankListViewHolder(bankListLayout);
        return bankListViewHolder;
    }

    @Override
    public void onBindViewHolder(BankListViewHolder holder, int position) {
        holder.bankName.setText(bankListModels.get(position).getBankName());

    }

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

    public class BankListViewHolder extends RecyclerView.ViewHolder {
        TextView bankName;

        public BankListViewHolder(View itemView) {
            super(itemView);
            bankName = (TextView) itemView.findViewById(R.id.tv_bankName);
            selectBank = itemView.findViewById(R.id.cv_selectBank);

        }
    }
}