代码将数据显示(绑定)到RecyclerView列表,但在向上滚动时会混淆视图设置

时间:2016-04-05 23:56:06

标签: android data-binding android-recyclerview

每次我向下滚动并备份我的RecyclerView时,我的布局会在数据发生变化时针对错误的项目进行更改。我正在显示体育比分,所以当比赛现场直播时,我注意到它会混淆视野。我已经查看了其他答案,但没有一个能帮助我确定我需要添加/更改以解决这个问题,所以我希望通过发布我的代码,有人可以证明我做错了什么这里。这是一个保管箱link,因此您可以看到我的屏幕截图。我在向下和向上滑动之间交替拍摄照片(最后两张照片除外,因为某些原因,Dropbox改变了顺序)。

这是我将数据绑定到ViewHolder的代码(对于长变量名称很抱歉,但它对我来说很清楚):

public class NBAGameHolder extends GameHolder implements View.OnClickListener
{
    /*NOTE: ONCE A GAME BEGINS:
    /       mGameStartTimeAndHomeScore will be used to display the home team score.
    /       mHomeTeamRecordAndQuarter will display the current quarter.
    /       mAwayTeamRecordAndTimeRem will display the time remaining in the quarter
     */

    private TextView mHomeTeam, mAwayTeam, mGameStartTimeAndHomeScore;
    private TextView mHomeTeamRecordAndQuarter, mAwayTeamRecordAndTimeRem, mAwayTeamScore, mFinalHeader;
    private ImageView mHomeTeamLogo, mAwayTeamLogo;
    private int mGreen, mDefaultGray;

    private Context mContext;

    public NBAGameHolder(View itemView, Context context)
    {
        super(itemView);
        mContext = context;
        itemView.setOnClickListener(this);

        mHomeTeam = (TextView) itemView.findViewById(R.id.home_team_name);
        mAwayTeam = (TextView) itemView.findViewById(R.id.away_team_name);
        mHomeTeamLogo = (ImageView) itemView.findViewById(R.id.home_team_logo);
        mAwayTeamLogo = (ImageView) itemView.findViewById(R.id.away_team_logo);
        mGameStartTimeAndHomeScore = (TextView) itemView.findViewById(R.id.game_time_home_team_score);
        mAwayTeamScore = (TextView) itemView.findViewById(R.id.away_team_score);
        mHomeTeamRecordAndQuarter = (TextView) itemView.findViewById(R.id.home_team_record_quarter);
        mAwayTeamRecordAndTimeRem = (TextView) itemView.findViewById(R.id.away_team_record_time_left_in_qrt);
        mFinalHeader = (TextView) itemView.findViewById(R.id.nba_final_header_text_view);
        mGreen = ContextCompat.getColor(mContext, R.color.green);
        mDefaultGray = ContextCompat.getColor(mContext, android.R.color.darker_gray);
    }

    public void bindNBAGameData(NBAGame game)
    {
        Picasso.with(mContext).load(game.getHomeTeamLogoSrc()).fit().into(mHomeTeamLogo);
        Picasso.with(mContext).load(game.getAwayTeamLogoSrc()).fit().into(mAwayTeamLogo);
        mHomeTeam.setText(game.getHomeTeam());
        mAwayTeam.setText(game.getAwayTeam());

        if(!game.getHomeTeamScore().equals("") && !game.gameEnded())        //if the game is live
        {
            mGameStartTimeAndHomeScore.setText(game.getHomeTeamScore());
            mAwayTeamScore.setText(game.getAwayTeamScore());
            mHomeTeamRecordAndQuarter.setText(game.getQuarter());
            mAwayTeamRecordAndTimeRem.setText(game.getTimeLeft());
            mHomeTeamRecordAndQuarter.setTextColor(ContextCompat.getColor(mContext, R.color.orange));
            mAwayTeamRecordAndTimeRem.setTextColor(ContextCompat.getColor(mContext, R.color.orange));
            mHomeTeamRecordAndQuarter.setTextSize(16);
            mAwayTeamRecordAndTimeRem.setTextSize(16);
            mFinalHeader.setVisibility(View.GONE);
        }
        else if(game.gameEnded())
        {
            mGameStartTime.setText(game.getHomeTeamScore());
            mAwayTeamScore.setText(game.getAwayTeamScore());
            int homeScore = Integer.parseInt(mGameStartTime.getText().toString());
            int awayScore = Integer.parseInt(mAwayTeamScore.getText().toString());
            mHomeTeamRecordAndQuarter.setText(game.getHomeTeamRecord());
            mHomeTeamRecordAndQuarter.setTextSize(12);
            mAwayTeamRecordAndTimeRem.setText(game.getAwayTeamRecord());
            mAwayTeamRecordAndTimeRem.setTextSize(12);
            mHomeTeamRecordAndQuarter.setTextColor(mDefaultGray);
            mAwayTeamRecordAndTimeRem.setTextColor(mDefaultGray);
            mFinalHeader.setVisibility(View.VISIBLE);

            if(homeScore > awayScore)
            {
                mGameStartTimeAndHomeScore.setTextColor(mGreen);    //displays winning team's score in green
                mAwayTeamScore.setTextColor(mDefaultGray);  //sets the losing team to the default dark gray color
                mHomeTeam.setTextColor(mGreen);
                mAwayTeam.setTextColor(mDefaultGray);
            }
            else
            {
                mAwayTeamScore.setTextColor(mGreen);
                mGameStartTimeAndHomeScore.setTextColor(mDefaultGray);  //sets the losing team to the default dark gray color
                mAwayTeam.setTextColor(mGreen);
                mHomeTeam.setTextColor(mDefaultGray);
            }
        }
        else                                                //game has not started
        {
            mGameStartTimeAndHomeScore.setText(game.getGameStartTime());
            mHomeTeamRecordAndQuarter.setText(game.getHomeTeamRecord());
            mAwayTeamRecordAndTimeRem.setText(game.getAwayTeamRecord());
            mAwayTeamScore.setText("");         
            mFinalHeader.setVisibility(View.GONE);
        }
    }

    @Override
    public void onClick(View v)
    {

    }
}

2 个答案:

答案 0 :(得分:1)

The issue is because of recycling of views.

所以这里发生的事情是列表项的属性被观察到与其他一些不需要的列表项视图的属性相关联。

在您的情况下,您需要为列表项中的每个视图设置TextView属性。

Example - 如果在条件满足的情况下将TextView的文本颜色设置为绿色,则需要将else块中的TextView的Text颜色设置为所需的默认颜色(在这种情况下)

同样,如果在条件满足时更改TextView的文本大小,则需要将else块中的TextView的文本大小也设置为该情况下所需的默认大小。

如果您要进行任何观看VISIBLE/INVISIBLE/GONE,则需要遵循相同的方法。

在任何if else if语句之上,您可以设置视图的默认属性,如下所示 -

mHomeTeamRecordAndQuarter.setTextColor();//Set default color here
mAwayTeamRecordAndTimeRem.setTextColor(); //Set default color here
mHomeTeamRecordAndQuarter.setTextSize(10);//Set default text size here 
mAwayTeamRecordAndTimeRem.setTextSize(10);//Set default text size here 
mFinalHeader.setVisibility(View.VISIBLE);//Set all those views visible here whose visibility is being changes in any of the if-else block

现在您可以在if-else块中成功更改视图的属性。 因此,对于那些未更改其属性的视图,这些视图仍将拥有默认属性。

答案 1 :(得分:0)

Adapter类内的数据绑定在onBindViewHolder()方法中 像这样:

@Override
        public void onBindViewHolder(NBAGameHolder holder, int position) {
            NBAGame game = itemsList.get(position);
            holder.mGameStartTime.setText(game.getHomeTeamScore());
    }