【问题标题】:RecyclerView displaying wrong data in other positionsRecyclerView 在其他位置显示错误数据
【发布时间】:2020-01-10 22:06:57
【问题描述】:

我正在创建一个带有卡片视图的 RecyclerView 我的 json 数据包含电影名称、年份、评级 我的卡片视图包含三个文本字段电影名称、评级、年份 当我单击评分字段时,它应该从 json 获取数据并在评分文本字段旁边显示评分,但这里的问题是当我单击文本字段时,我的卡片视图的数据也会显示在卡片视图的其他位置.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mList = findViewById(R.id.recylcerview);
    movieList = new ArrayList<>();
    builder = new AlertDialog.Builder(this);
    adapter = new MovieAdapter(this, movieList);
    linearLayoutManager = new LinearLayoutManager(this);
    dividerItemDecoration = new DividerItemDecoration(mList.getContext(), linearLayoutManager.getOrientation());
    mList.setHasFixedSize(true);
    mList.setLayoutManager(linearLayoutManager);
    mList.addItemDecoration(dividerItemDecoration);
    mList.setAdapter(adapter);
    if ((isNetworkConnected() == true)) {
        getData();
    } else {
        builder.setTitle("turn on internet");
        builder.setCancelable(false);
        builder.setPositiveButton("ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.dismiss();
            }

        });
        builder.create();
        builder.show();
    }

}

@Override
protected void onResume() {
    super.onResume();
    if ((isNetworkConnected() == true)) {
        getData();
        adapter.notifyDataSetChanged();
    } else {
        builder.setTitle("turn on internet");
        builder.setCancelable(false);
        builder.setPositiveButton("ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.dismiss();
            }

        });
        builder.create();
        builder.show();
    }
}

public String loadJSONFromAsset() {
    String json = null;
    try {
        InputStream is = this.getAssets().open("data.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return json;
}

private void getData() {
    builder = new AlertDialog.Builder(this);
    try {
        JSONObject reader = new JSONObject(loadJSONFromAsset());
        JSONArray jArray = reader.getJSONArray("rootnode");
        for (int i = 0; i < jArray.length(); i++) {
            try {
                JSONObject jsonObject = jArray.getJSONObject(i);

                Movie movie = new Movie();
                movie.setTitle(jsonObject.getString("title"));
                movie.setRating(jsonObject.getDouble("rating"));
                movie.setYear(jsonObject.getInt("releaseYear"));
                movieList.add(movie);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            adapter.notifyDataSetChanged();

        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

private boolean isNetworkConnected() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected();
}

我的回收站视图中不应有任何重复数据

public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> {
    private Context context;
    Movie movie;

    public MovieAdapter(Context context, ArrayList<Movie> list) {
        this.context = context;
        this.list = list;
    }

    private ArrayList<Movie> list;


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(context).inflate(R.layout.single_item, parent, false);
        final ViewHolder viewHolder = new ViewHolder(v);
        viewHolder.view_container.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Intent i=new Intent(context,Main2Activity.class);
                //   String a=list.get(viewHolder.getAdapterPosition()).getTitle();
                //   Double b=list.get(viewHolder.getAdapterPosition()).getRating();
                //  int c=list.get(viewHolder.getAdapterPosition()).getYear();
                //  String g =String.valueOf(c);

                // viewHolder.textYear.setText(g);


                //   i.putExtra("movie",a);
                //   i.putExtra("rating",b);
                //   i.putExtra("year",c);
                //   context.startActivity(i);
            }
        });
        viewHolder.something.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Double w = list.get(viewHolder.getAdapterPosition()).getRating();
                String k = Double.toString(w);
                viewHolder.textRating.setText(k);
            }
        });
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
        movie = list.get(position);

        holder.textTitle.setText(movie.getTitle());
        holder.view_container.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int c = list.get(holder.getAdapterPosition()).getYear();
                String g = String.valueOf(c);

                holder.textYear.setText(g);

            }
        });
        // holder.textRating.setText(String.valueOf(movie.getRating()));
        // holder.textYear.setText(String.valueOf(movie.getYear()));
    }

    @Override
    public int getItemCount() {

        return list.size();
    }


    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView view_container;
        TextView something;
        public TextView textTitle, textRating, textYear;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            view_container = itemView.findViewById(R.id.textView5);
            something = itemView.findViewById(R.id.Rating);
            textTitle = itemView.findViewById(R.id.title);
            textRating = itemView.findViewById(R.id.textView2);
            textYear = itemView.findViewById(R.id.main_year);
        }
    }
}

【问题讨论】:

  • 这就是 RecyclerView 的使用方式——视图被重用。并且如果文本已经设置为TextView,如果在其他位置不需要,则需要将其移除。
  • 最好使用POJO类来维护itemview的状态。如果没有,recycler view 会回收你的 view 并显示错误的数据。
  • 奇怪的是,您在调用getData() 两次时没有遇到重复数据问题,在onCreateonResume 上也是如此。
  • @DHAVALASODARIYA 是的,你是对的,我有重复的数据,我删除了它
  • 你必须改变你的逻辑,据我所知,你这样做是不可能的,将你的监听器位置从 RecyclerView 类更改为 Application 类,并尝试处理那里的点击。跨度>

标签: android json android-studio listview android-recyclerview


【解决方案1】:

永远不要将数据与onCreateViewHolder 方法中的视图绑定,因为您在点击something' ,holder.textYear.setText(g); 时已经这样做了;`

因此,我建议您不要像这样管理它,而是以可见性管理您的评级文本视图。

只需在onBindViewHolder() 中移动您的点击操作,然后对其进行以下更改。

    Double w = list.get(viewHolder.getAdapterPosition()).getRating();
    String k = Double.toString(w);
    viewHolder.textRating.setText(k);

    viewHolder.textRating.setVisibility(View.INVISIBLE);

    viewHolder.something.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            viewHolder.textRating.setVisibility(View.VISIBLE);
        }
    });

维持审核状态:

首先在模型类中创建一个布尔变量并为此生成 getter-setter。

private boolean isReviewedVisible = false;

public boolean isReviewedVisible() {
    return isReviewedVisible;
}

public void setIsReviewedVisible(boolean isVisible) {
    this.isReviewedVisible = isVisible;
}

onBindViewHolder() 方法中添加以下检查。

    if(movie.isReviewedVisible()){
       viewHolder.textRating.setVisibility(View.VISIBLE);
    } else {
       viewHolder.textRating.setVisibility(View.INVISIBLE);
    }
    viewHolder.something.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            movie.setReviewedVisible(true);
            viewHolder.textRating.setVisibility(View.VISIBLE);
        }
    });

【讨论】:

  • @DHAVALASHODARIYA 它有效,但是当我向上和向下滚动时,数据是不可见的任何解决方案??
  • 然后你需要在你的模型类中管理状态。让我更新我的代码。
  • @dineshreddy 我已经更新了我的答案。请检查它。
  • @DHAVALASHODARIYA 我没有得到任何东西我应该在 isReviewedVisible() 方法中提到什么
  • @dineshreddy 哦。对不起。我忘了提,你还需要在那个模型类中生成getter-setter。
猜你喜欢
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
相关资源
最近更新 更多