具有<include>标签的视图在RecyclerView android中不会更新

时间:2018-08-28 13:11:01

标签: android android-layout android-recyclerview recycler-adapter

视图(甚至视图的子元素)不会更新,但会复制RecyclerView中的上一项。 我有树transaction_status_tree.xml的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:ignore="UselessParent">

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/dotConfirmed"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/non_filled_progress_dot"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvConfirmed"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/BflSansTextViewStyle"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/confirmed"
                tools:ignore="RtlHardcoded" />

        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/progress_line"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvConfirmedInfo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/BflSansTextViewStyle"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/not_yet"
                android:textSize="@dimen/txt_small_size"
                android:textStyle="italic"
                tools:ignore="RtlHardcoded" />
        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/dotPickedCashier"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/non_filled_progress_dot"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvPickedCashier"
                style="@style/BflSansTextViewStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/picked_by_cashier"
                tools:ignore="RtlHardcoded" />

        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/progress_line"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvPickedCashierInfo"
                style="@style/BflSansTextViewStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/not_yet"
                android:textSize="@dimen/txt_small_size"
                android:textStyle="italic"
                tools:ignore="RtlHardcoded" />
        </TableRow>

        <TableRow
            android:id="@+id/trTransferred"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/dotTransferred"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/non_filled_progress_dot"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvTransferred"
                style="@style/BflSansTextViewStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/transferred"
                tools:ignore="RtlHardcoded" />
        </TableRow>

        <TableRow
            android:id="@+id/trTransferredInfo"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/progress_line"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvTransferredInfo"
                style="@style/BflSansTextViewStyle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/not_yet"
                android:textSize="@dimen/txt_small_size"
                android:textStyle="italic"
                android:visibility="visible"
                tools:ignore="RtlHardcoded" />
        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/dotSubmitted"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:srcCompat="@drawable/filled_progress_dot"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvSubmitted"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/BflSansTextViewStyle"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/submitted"
                android:textStyle="bold"
                tools:ignore="RtlHardcoded" />

        </TableRow>

        <TableRow
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:layout_width="8dp"
                android:layout_height="8dp"
                android:layout_gravity="center"
                app:srcCompat="@drawable/filled_progress_dot"
                tools:ignore="ContentDescription" />

            <com.bfl.delivery.customviews.BflTextView
                android:id="@+id/tvSubmittedInfo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/BflSansTextViewStyle"
                android:layout_marginLeft="@dimen/default_material_margin"
                android:layout_marginStart="@dimen/default_material_margin"
                android:text="@string/not_yet"
                android:textSize="@dimen/txt_small_size"
                android:textStyle="italic"
                tools:ignore="RtlHardcoded" />
        </TableRow>
    </TableLayout>

</FrameLayout>

我正在卡片(列表项)card_transaction_item.xml中用<include>标签使用它:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- View to resolve problem with GONE first item in SwipeRefreshLayout -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp" />

    <android.support.v7.widget.CardView
        android:id="@+id/cvTh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/default_min_divider"
        app:cardCornerRadius="0dp">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                tools:ignore="UselessParent">

                <com.bfl.delivery.customviews.BflTextView
                    android:id="@+id/tvIdTh"
                    style="@style/BflTextViewStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="@dimen/default_material_margin"
                    android:layout_marginStart="@dimen/default_material_margin"
                    android:layout_marginTop="@dimen/default_material_margin"
                    android:text="Transaction number"
                    android:textSize="@dimen/txt_card_title_size"
                    android:textStyle="bold"
                    tools:ignore="HardcodedText" />

                <com.bfl.delivery.customviews.BflTextView
                    android:id="@+id/tvCodeTh"
                    style="@style/BflSansTextViewStyle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="@dimen/default_material_margin"
                    android:layout_marginStart="@dimen/default_material_margin"
                    android:text="BFL[xxxxxxxxxx]"
                    android:textSize="@dimen/txt_tiny_size"
                    tools:ignore="HardcodedText" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginEnd="@dimen/default_material_margin"
                    android:layout_marginStart="@dimen/default_material_margin"
                    android:layout_marginTop="@dimen/default_min_divider"
                    android:orientation="horizontal">

                    <com.bfl.delivery.customviews.BflTextView
                        android:id="@+id/tvThTimeStamp"
                        style="@style/BflSansTextViewStyle"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginEnd="@dimen/default_material_margin"
                        android:layout_marginRight="@dimen/default_material_margin"
                        android:layout_weight="1"
                        android:text="00-00-0000 00:00"
                        tools:ignore="HardcodedText,RtlHardcoded" />

                    <com.bfl.delivery.customviews.BflTextView
                        android:id="@+id/tvThMoney"
                        style="@style/BflSansTextViewStyle"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="2"
                        android:text="$0000"
                        android:textAlignment="viewEnd"
                        tools:ignore="HardcodedText" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/llExpandTree"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginBottom="@dimen/default_min_divider"
                    android:layout_marginTop="@dimen/default_min_divider"
                    android:clickable="true"
                    android:focusable="true"
                    android:foreground="?android:attr/selectableItemBackground"
                    android:orientation="horizontal"
                    android:paddingBottom="20dp"
                    android:paddingTop="20dp">

                    <com.bfl.delivery.customviews.BflTextView
                        android:id="@+id/tvCntStatusTh"
                        style="@style/BflSansSemiBoldTextViewStyle"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:layout_marginStart="@dimen/default_material_margin"
                        android:layout_weight="1"
                        android:ellipsize="end"
                        android:text="Current status"
                        tools:ignore="HardcodedText,InefficientWeight" />

                    <FrameLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:layout_weight="3">

                        <ImageView
                            android:id="@+id/ivExpandTh"
                            android:layout_width="20dp"
                            android:layout_height="20dp"
                            android:layout_gravity="center_vertical|end"
                            android:layout_marginEnd="@dimen/default_material_margin"
                            app:srcCompat="@drawable/expand"
                            tools:ignore="ContentDescription" />
                    </FrameLayout>

                </LinearLayout>

                <include
                    android:id="@+id/statusTreeTh"
                    layout="@layout/transaction_status_tree"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="@dimen/default_material_margin"
                    android:layout_marginEnd="@dimen/default_material_margin"
                    android:layout_marginStart="@dimen/default_material_margin"
                    android:visibility="gone" />

            </LinearLayout>
        </FrameLayout>
    </android.support.v7.widget.CardView>
</FrameLayout>

因此,当我尝试刷新包含新项目的列表时,除该树以外的所有视图(例如,所有TextView)都成功更新。该树将成为RecyclerView中上一个卡片(项目)中树的副本。

我有这样的适配器:

public class TransactionsCardAdapter extends RecyclerView.Adapter<TransactionsCardAdapter.TcaViewHolder> {

    private Context mContext;
    private List<TransactionCardData> cardsData;

    public TransactionsCardAdapter (Context mContext, List<TransactionCardData> cardsData) {
        this.mContext = mContext;
        this.cardsData = cardsData;
    }

    class TcaViewHolder extends RecyclerView.ViewHolder {

        TextView tvNumber;
        TextView tvCode;
        TextView tvTime;
        TextView tvMoney;
        TextView tvCntStatus;
        ImageView ivExpand;
        CardView cv;
        View tree;
        ImageView ivSubmitted;
        TextView tvSubmitted;
        TextView tvSubmittedDate;
        ImageView ivTransferred;
        TextView tvTransferred;
        TextView tvTransferredDate;
        ImageView ivPickedCashier;
        TextView tvPickedCashier;
        TextView tvPickedCashierDate;
        ImageView ivConfirmed;
        TextView tvConfirmed;
        TextView tvConfirmedDate;
        View expandView;

        View trTransferred;
        View trTransferredInfo;

        TcaViewHolder(View v) {
            super(v);
            tvNumber = v.findViewById(R.id.tvIdTh);
            tvCode = v.findViewById(R.id.tvCodeTh);
            tvTime = v.findViewById(R.id.tvThTimeStamp);
            tvMoney = v.findViewById(R.id.tvThMoney);
            tvCntStatus = v.findViewById(R.id.tvCntStatusTh);
            ivExpand = v.findViewById(R.id.ivExpandTh);
            cv = v.findViewById(R.id.cvTh);
            tree = v.findViewById(R.id.statusTreeTh);
            tvSubmitted = tree.findViewById(R.id.tvSubmitted);
            tvSubmittedDate = tree.findViewById(R.id.tvSubmittedInfo);
            ivSubmitted = tree.findViewById(R.id.dotSubmitted);
            tvTransferred = tree.findViewById(R.id.tvTransferred);
            tvTransferredDate = tree.findViewById(R.id.tvTransferredInfo);
            ivTransferred = tree.findViewById(R.id.dotTransferred);
            ivPickedCashier = tree.findViewById(R.id.dotPickedCashier);
            tvPickedCashier = tree.findViewById(R.id.tvPickedCashier);
            tvPickedCashierDate = tree.findViewById(R.id.tvPickedCashierInfo);
            tvConfirmed = tree.findViewById(R.id.tvConfirmed);
            tvConfirmedDate = tree.findViewById(R.id.tvConfirmedInfo);
            ivConfirmed = tree.findViewById(R.id.dotConfirmed);
            expandView = v.findViewById(R.id.llExpandTree);

            trTransferred = v.findViewById(R.id.trTransferred);
            trTransferredInfo = v.findViewById(R.id.trTransferredInfo);
        }
    }

    @NonNull
    @Override
    public TcaViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_transaction_item, parent, false);

        return new TransactionsCardAdapter.TcaViewHolder(itemView);
    }

    @SuppressLint("DefaultLocale")
    @Override
    public void onBindViewHolder(@NonNull final TcaViewHolder holder, int position) {
        final TransactionCardData item = cardsData.get(position);
        String formattedId = String.format("%012d", item.getId());
        holder.tvNumber.setText(formattedId);
        holder.tvCode.setText(item.getPackageId());
        String amount = String.valueOf(item.getMoney()) + " " + mContext.getString(R.string.uah);
        holder.tvMoney.setText(amount);

        String cntStatus;

        /* Setting current status in title */
        if (item.getStatusConfirmed() != null) {
            cntStatus = mContext.getResources().getString(R.string.confirmed);
        } else if (item.getStatusPickedCashier() != null) {
            cntStatus = mContext.getResources().getString(R.string.picked_by_cashier);
        } else if (item.getStatusTransferred() != null) {
            cntStatus = mContext.getResources().getString(R.string.transferred);
        } else {
            cntStatus = mContext.getResources().getString(R.string.submitted);
        }

        /* Making dots */
        if (item.getStatusConfirmed() != null) {
            makeConfirmed(item.getStatusConfirmed(), holder);
        }
        if (item.getStatusTransferred() != null) {
            makeTransferred(item.getStatusTransferred(), holder);
        }
        if (item.getStatusPickedCashier() != null) {
            makePickedCashier(item.getStatusPickedCashier(), holder);
        }
        if (item.getStatusSubmitted() != null) {
            makeSubmitted(item.getStatusSubmitted(), holder);
        }

        /* Hiding dot if necessary */
        if (item.getStatusTransferred() == null && item.getStatusPickedCashier() != null) {
            holder.trTransferred.setVisibility(View.GONE);
            holder.trTransferredInfo.setVisibility(View.GONE);
        }

        holder.tvCntStatus.setText(cntStatus);
        holder.tvTime.setText(item.getTimeSubmitted());

        holder.expandView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                expandOrCollapse(holder);
            }
        });

    }

    private void makeSubmitted (String dateTime, TcaViewHolder holder) {
        holder.tvSubmittedDate.setText(dateTime);
        holder.tvSubmitted.setTypeface(null, Typeface.BOLD);
        holder.ivSubmitted.setImageDrawable(
                ContextCompat.getDrawable(mContext, R.drawable.filled_progress_dot)
        );
    }

    private void makePickedCashier (String dateTime, TcaViewHolder holder) {
        holder.tvPickedCashierDate.setText(dateTime);
        holder.tvPickedCashier.setTypeface(null, Typeface.BOLD);
        holder.ivPickedCashier.setImageDrawable(
                ContextCompat.getDrawable(mContext, R.drawable.filled_progress_dot)
        );
    }

    private void makeTransferred (String dateTime, TcaViewHolder holder) {
        holder.tvTransferredDate.setText(dateTime);
        holder.tvTransferred.setTypeface(null, Typeface.BOLD);
        holder.ivTransferred.setImageDrawable(
                ContextCompat.getDrawable(mContext, R.drawable.filled_progress_dot)
        );
    }

    private void makeConfirmed (String dateTime, TcaViewHolder holder) {
        holder.tvConfirmedDate.setText(dateTime);
        holder.tvConfirmed.setTypeface(null, Typeface.BOLD);
        holder.ivConfirmed.setImageDrawable(
                ContextCompat.getDrawable(mContext, R.drawable.filled_progress_dot)
        );
    }

    private void expandOrCollapse (@NonNull final TcaViewHolder holder) {
        long animDuration = 100;
        if (holder.tree.getVisibility() == View.GONE) {
            holder.tree.setVisibility(View.VISIBLE);
            holder.ivExpand.animate().rotation(180).setDuration(animDuration);
        } else {
            holder.tree.setVisibility(View.GONE);
            holder.ivExpand.animate().rotation(0).setDuration(animDuration);
        }
    }

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

    public void updateData (List<TransactionCardData> nData) {
        cardsData.clear();
        cardsData.addAll(nData);
        notifyDataSetChanged();
    }

}

我正在使用updateData (List<TransactionCardData> nData);更新列表。 请给我解释一下,我在做什么错以及为什么会发生此问题。

1 个答案:

答案 0 :(得分:1)

RecyclerView重用现有视图,而不是再次夸大它们。因此,所有未显式更新的字段将从其他视图复制。如果未显式隐藏或更新子项(例如当它们为null时),则将使用旧值。因此,您将必须为每个子视图添加一个else案例。就像某些值是null一样,在else情况下将其隐藏。

 if (item.getStatusConfirmed() != null) {
       makeConfirmed(item.getStatusConfirmed(), holder);
 } else {
        view.setVisibilty(View.GONE);
 }