当我将ViewHolder作为RecyclerView.Adapter的类成员时,为什么getAdapterPosition返回错误的值

时间:2017-03-13 15:29:22

标签: java android android-recyclerview

我遇到了一个奇怪的问题。我在互联网上搜索过,但看起来没有同样的问题。

在FruitAdapter.java中,如果我使 ViewHolder 成为 RecyclerView 的类成员,那么 getAdapterPosition 将返回错误的值!!!。< / p>

如果我将ViewHolder作为RecyclerView&#39;函数局部变量,无错误。 ViewHolder在onCreateViewHolder上的相同位置构建,

在FruitAdapter.java中,

这是代码。

MainActivity.java

package com.example.recyclerviewtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private List<String> fruitList = new ArrayList<String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        LinearLayoutManager linerLayoutManager = new LinearLayoutManager(MainActivity.this);
        recyclerView.setLayoutManager(linerLayoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    }

    private void initFruits() {
        for (int i = 0; i < 2; i++) {

            fruitList.add("apple");
            fruitList.add("banana");
            fruitList.add("orange");
            fruitList.add("watermelon");
            fruitList.add("pear");

           }
    }
}

FruitAdapter.java

package com.example.recyclerviewtest;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{

    private List<String> mFruitList;


    **//if I use below, I got the Problem
    //ViewHolder holder;**

    static class ViewHolder extends RecyclerView.ViewHolder {
        View fruitView;

        TextView fruitName;

        public ViewHolder(View view) {
            super(view);
            fruitView = view;

            fruitName = (TextView) view.findViewById(R.id.fruitItemName);
        }
    }

    public FruitAdapter(List<String> fruitList) {
        mFruitList = fruitList;
    }

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

        //this works, but if holder is class member,then problems happen
        final ViewHolder holder = new ViewHolder(view);
        //holder = new ViewHolder(view);

        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                String fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked view " + fruit, Toast.LENGTH_SHORT).show();
            }
        });

        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit);
    }
    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}

2 个答案:

答案 0 :(得分:0)

如果onCreateViewHolder池中没有ViewHolder,则会调用

ViewHolder,因此RecyclerView必须创建一个新ViewHolder

假设列表中有100个项目,屏幕上一次只显示10个项目。当你滚动到例如列表中的第15项,顶部RecyclerView将被回收并在它们不再可见时立即放入池中。但是,新项目应该可见,因此ViewHolder会从池中为每个项目提取新的onBindViewHolder()并调用onCreateViewHolder注意ViewHolder不再被调用,因为它已经创建并存在于池中。

当您保留对onCreateViewHolder中创建的ViewHolder的引用时,您会引用getAdapterPosition(),这不是您想要的。在这个例子中,它会让我们说11。所以,当你滚动到第80个项目时,你仍然会得到11作为onCreateViewHolder()值。

此外,ViewHolder方法,正如其名称所示,用于创建onBindViewHolder(),仅此而已。要设置视图,请setOnClickListener()。因此,请从onBindViewHolder()回调执行您的设置逻辑(例如var manager = new RedmineManager("http://srvredmine/login", username, password); )。

答案 1 :(得分:-1)

谢谢,azizbekian&安培;布拉德利威尔逊,

你是对的。在onBindViewHolder中放入onclick逻辑后,奇怪的事情就消失了。

询价布拉德利·威尔逊的评论“onCreateViewHolder是他们创造viewHolder但它直到你完成通过onBindViewHolder项目,循环不将项目绑定到RecyclerView”

但其中一个仍然很奇怪,为什么函数局部变量有效。