【问题标题】:Read data in activity of recyclerview adapter读取 recyclerview 适配器活动中的数据
【发布时间】:2020-05-31 01:04:29
【问题描述】:

我有一个带有卡片和微调器的 recyclerview,在微调器中选择的值我需要将其发送到下一个活动以计算估计价格。我在活动中有一个不属于 recyclerview 的按钮,它会将我带到我需要这些值的下一个活动。因此,当我单击此按钮时,我需要它来收集数据并将其发送到下一个活动,我该如何实现。

我附上了一张图片。红色箭头(我在下一个活动中需要的数据),蓝色箭头(按下按钮将我带到下一个活动)

Screenshot of screen

我正在使用这种方法来读取值

findMerchantTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                for (int i = 0; i < totalCards; i++) {
                    Spinner printColorSpinner = mRecyclerView.findViewHolderForLayoutPosition(i).itemView.findViewById(R.id.printColorSpinner);
                    Spinner printSidesSpinner = mRecyclerView.findViewHolderForAdapterPosition(i).itemView.findViewById(R.id.printSidesSpinner);
                    Spinner printSizeSpinner = mRecyclerView.findViewHolderForAdapterPosition(i).itemView.findViewById(R.id.paperSizeSpinner);
                    Spinner pagesSpinner = mRecyclerView.findViewHolderForAdapterPosition(i).itemView.findViewById(R.id.pagesSpinner);
                    Spinner orientationSpinner = mRecyclerView.findViewHolderForAdapterPosition(i).itemView.findViewById(R.id.orientationSpinner);
                    Spinner bindingTypeSpinner = mRecyclerView.findViewHolderForAdapterPosition(i).itemView.findViewById(R.id.bindingTypeSpinner);
                    MaterialTextView copiesTextView = mRecyclerView.findViewHolderForAdapterPosition(i).itemView.findViewById(R.id.copiesNumberText);
                    String color = printColorSpinner.getSelectedItem().toString().trim();
                    String sides = printSidesSpinner.getSelectedItem().toString().trim();
                    String size = printSizeSpinner.getSelectedItem().toString().trim();
                    String pages = pagesSpinner.getSelectedItem().toString().trim();
                    String orientation = orientationSpinner.getSelectedItem().toString().trim();
                    String bindingType = bindingTypeSpinner.getSelectedItem().toString().trim();
                    String totalCopies = copiesTextView.getText().toString().trim();
                }
            }
        });

但是当i变成2时,findViewHolderForLayoutPosition返回NullPointerException。我搜索并知道视图被回收了,只有在屏幕上布置的视图才能读取。

获得这些值的替代方法是什么?谢谢!

【问题讨论】:

    标签: android android-recyclerview android-viewholder


    【解决方案1】:

    RecyclerView 重用视图以提高性能和内存消耗,并且您只能访问可见视图。实现目标的一种方法是使用接口进行包含 RecyclerView 和 Adapter 的 Activity 之间的交互,它们会更新对象的主数组。

    示例:

    1. 假设您有一个类来定义您的数据。

    YourClass.java

    public class YourClass extends Object implements Parcelable {
    
      public String color = "";
      public String sides = "";
      public String size = "";
      public String pages = "";
      public String orientation = "";
      public String bindingType = "";
      public String totalCopies = "";
    
      //... your methods and implementations
    }
    
    1. 让我们定义一个接口来处理微调器的事件

    AdapterSpinnerListener.java

    public interface AdapterSpinnerListener {
        public void onSpinnerChanged(String spinnerType, String spinnerValue,  int position);
    
        //... other events
    }
    
    1. 为您的 RecyclerView 实现自定义适配器

    CustomAdapter.java

    public class CustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private AdapterActionListener adapterActionListener;
    
        // Your constructor receive the Fragment of Activity which implements the AdapterSpinnerListener.
        // Also receive the array of objects to populate the RecyclerView
        public CustomAdapter(YourActivity activity, ArrayList<YourClass> customRows)
        {
          this.adapterActionListener = activity;
        }
    
        //... implements all the needed functions for the RecyclerView
        //getItemId
        //getItemCount
        //getItemViewType
        //onCreateViewHolder
    
        //In your onBindViewHolder, you should add a listener for each one of your spinners. 
        //Also I'm supossing you have a CustomViewHolder to reference the Layout and Spinners.
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
          CustomViewHolder holder = (CustomViewHolder)viewHolder;
          holder.textViewSomething.setText(...);
    
          holder.printColorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
              @Override
              public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                  if (adapterActionListener != null) {
                      // You can retrieve the selected item using parent.getItemAtPosition(pos)
                      adapterActionListener.onSpinnerChanged("color", selectedValue,  position);
                  }
              }
    
              @Override
              public void onNothingSelected(AdapterView<?> adapterView) {
    
              }
          });
    
          //holder.printSidesSpinner.setOnItemSelectedListener...
          //...
          //...
          //... You should implement a listener for each spinner
        }
    }
    
    1. 在包含 RecyclerView 的 Activity 或 Fragment 中,您应该实现接口并定义对象数组并使用数据填充适配器。

    YourActivity.java

    public class YourActivity extends AppCompatActivity implements AdapterSpinnerListener {
        private RecyclerView recyclerView;
        private CustomAdapter customAdapter;
        private ArrayList<YourClass> customRows;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.your_activity);
    
            recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            customAdapter = new CustomAdapter(this, customRows);
            recyclerView.setAdapter(customAdapter);
            recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity()));
        }
    
      // Implements the method of the interface
      @Override
      public void onSpinnerChanged(String spinnerType, String spinnerValue,  int position) {
        if (spinnerType.equals("color")) {
          customRows.get(position).color = spinnerValue;
        } else if (spinnerType.equals("sides")) {
          customRows.get(position).sides = spinnerValue;
        }
        //...
        //...
      }
    }
    
    1. 现在微调器的值位于 customRows 数组中。您可以在点击事件中检索值
    findMerchantTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
    
                for (int i = 0; i < customRows.size(); i++) {
                    String color = customRows.get(i).color;
                    String sides = customRows.get(i).sides;
                    //...
                    //...
                    //... all the values you want to get for the next activity
                    //... 
                }
            }
        });
    

    【讨论】:

    • 非常感谢!我该如何处理 totalCopies?那不是微调器,它是一个文本视图。它会是 for (int i = 0; i
    • 为什么我们将值在微调器中的位置传递给 customRows.get(position) ?
    • @AbhishekAN 1) 是正确的,在 findMerchantTextView onClick 中我缺少size() 方法,我使用变量position 而不是i。 2)我们在两个地方传递位置值:onItemSelected 用于触发我更改了哪个微调器的接口函数(微调器类型),微调器值和position 用于引用该微调器所属的行。另一个地方是onSpinnerChanged,您可以在其中接收触发事件并更新正确的 customRows 对象。 customRows 持有 RecyclerView 中每个显示行的数据引用。
    • 关于textView:和我贴的例子几乎是一样的逻辑。您应该在界面中创建一些其他事件,例如onTextChanged(String text, int position) 。然后在onBindViewHolder 上,您需要使用addTextChangedListener 将侦听器添加到您的持有者textView 并触发引用onTextChanged 内部位置的事件。之后,您将能够收到 Activity 中特定位置的文本数据。
    • adapterActionListener.onSpinnerChanged("color", selectedValue, pos);这里应该通过位置而不是位置。非常感谢您的帮助!
    【解决方案2】:

    假设每个微调器选择一件物品:

    在您的 RecyclerView 的 adapter 中:

    class MyAdapter extends ...........{
    
    //have these as member fields
    public String color = "default";
    public String sides = "default";
    public String size = "default";
    public String pages = "default";
    public String orientation = "default";
    public String bindingType = "default";
    public String totalCopies = "default";
    .......
    .......
    
    
    //when you interact with the spinners in onBindViewHolder
    
    @Override
    public void onBindViewHolder(........){
    
    //on selecting color spinner item
    
    holder.colorSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
    
          //set the color here  
          color = 
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
    
        }
    
    });
    
    
    //on selecting sides spinner item
    
    holder.sidesSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
    
          //set the sides here  
          sides = 
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parentView) {
    
        }
    
    });
    
    // you get the idea, do the rest here..........
    
    }
    
    
    
    
    
    
    }
    

    在包含您要单击以发送数据的 Button 的 Activity 中:

    class YourActivity extends .........{
    
    
    
    
    //lets say you initialized the adapter like this
    
    MyAdapter adapter = new MyAdapter(.....);
    
    //when you click the button:
    
    
    findMerchantTextView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    
    Intent intent = new Intent(YourActivity.this , TheOtherActivityName.class);
    intent.putExtra("color" , adapter.color);
    intent.putExtra("sides" , adapter.sides);
    intent.putExtra("size" , adapter.size);
    intent.putExtra("pages" , adapter.pages);
    intent.putExtra("orientation" , adapter.orientation);
    intent.putExtra("bindingType" , adapter.bindingType);
    intent.putExtra("totalCopies" , adapter.totalCopies);
    startActivity(intent);
    
    }
    
    });
    
    
    
    
    }
    

    在要读取按钮传递的数据的activity中:

    class TheOtherActivityName extends .....{
    
    //in onCreate()
    
    
    String color = getIntent.getStringExtra("color");
    String sides = getIntent.getStringExtra("sides");
    String size = getIntent.getStringExtra("size");
    ........
    ........
    ........
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多