【问题标题】:Android: RecyclerView's CardView Not Showing Every TimeAndroid:RecyclerView 的 CardView 每次都不显示
【发布时间】:2019-08-25 23:49:48
【问题描述】:

我在 MainActivity 中有一个 RecyclerView,它显示了 CardViews 列表并且工作正常。点击 CardView 完成 RecyclerView Activity 并启动一个 Detail Activity,在新的 RecyclerView 列表中显示点击的 CardView。 Detail Activity 仅用于在 RecyclerView 中显示单个 CardView(我这样做是为了在 CardView 上使用 RecyclerView 的 ItemTouchHelper.SimpleCallback 代码,以便用户向左滑动)。

这是问题所在:我点击了 Detail Activity 工具栏上的左插入符以返回 MainActivity。然后单击完全相同的 CardView 将用户带回 Detail Activity。但这次只显示背景视图(边框)。 CardView 及其数据库数据的视图完全丢失。

错误似乎是随机发生的。我可以点击从MainActivity到Detail Activity来回成功5次,然后在第六次尝试时,Detail Activity中不会显示CardView。或者我点击两次成功,然后第三次,DetailActivity中的CardView就不显示了。请注意 Detail Activity 中的左插入符号单击使用 onBackPressed() ,因此 Detail Activity 完成。所以我认为不应该有任何后堆栈问题。我还尝试将 CardView 的 xml 高度调整为 match_parent 而不是 wrap_content 但没有运气。 Detail Activity 的 ViewModel 到 Repository 到 Dao 返回一个包裹在 LiveData 中的 List。也许 ViewModel 存在观察者问题,但我认为当 Detail Activity 被销毁时,观察者会被移除/销毁?我在这里错过了什么?

适配器

...
itemHolder.cardView.setOnClickListener(view -> {

Card adapterItem= TodosAdapter.this.getItem(itemHolder.getAdapterPosition()); 
            int adapPos = itemHolder.getAdapterPosition();
            if (adapPos !=RecyclerView.NO_POSITION) {
                onItemClick(adapPos, adapterItem);
            }
        });

主活动

...
public void onItemClick(int clickPos, Card cardFromClick) {
    Intent intent = new Intent(MainActivity.this, DetailActivity.class);
        intent.putExtra("TAG","fromMain");
        intent.putExtra("itemFromMain", cardFromClick);
        startActivity(intent);
        finish();    

详细活动

...
public class DetailActivity extends AppCompatActivity {

private int cardId = -1;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_details);

    // Get a new or existing ViewModel from the ViewModelProvider.
    detsViewModel = new ViewModelProvider(this).get(CardViewModel.class);

    Toolbar toolbar = findViewById(R.id.toolbar);        
        // The left caret is for Up navigation to the previous activity
        // for OS versions 4.0 and earlier.
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        toolbar.setNavigationIcon(R.drawable.ic_action_previous_item);            
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });            
    }

    Intent intent = getIntent();
    Bundle extras = intent.getExtras(); 

    if (extras != null) {
        String classname = extras.getString("TAG");

        // The user clicked on a Card in the MainActivity
        if (classname != null && classname.equals("fromMain")) {
            card = extras.getParcelable("itemFromMain");
            if (card != null) {
                cardId = card.getId(); // card data is stored in Room database.
            }
        }
    }

    detsViewModel.getSingleCard(cardId).observe(this, singleAdapterList -> {

        adapter2.setCardList(singleAdapterList);            
    });
}

activity_details.xml

...
<RelativeLayout

xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
tools:context=".DetailsActivity"  >

<include
    android:id="@+id/toolbar"
    layout="@layout/toolbar" >
</include>

<RelativeLayout
    android:id="@+id/todoListLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/toolbar"  >

    <TextView
        android:id="@+id/Card"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:text="Card"
        android:textStyle="bold"
        android:textColor="@color/text_primary"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_centerHorizontal="true"  />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/details_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_below="@+id/Card"
        android:scrollbars="vertical"  />

    <TextView
        android:id="@+id/skytext5"
        android:text="Cards"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/details_recyclerview"
                    android:background="@color/colorPrimary"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:clickable="true"
        android:focusable="true"  />        

</RelativeLayout>

DetailsAdapter

...
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View itemView = LayoutInflater.from(mContext).inflate(R.layout.details_list_item, parent, false);
}

private List<Card> oneCardList

public void setCardList(List<Card> singleCardList) {

    if (oneCardList != null) {
        oneCardList.clear();
        this.oneCardList = singleCardList;
    } else {
        // First initialization
        this.oneCardList = singleCardList;
    }
}

details_list_item.xml

...
<FrameLayout

xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/detsinglecard_view"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:foreground="?android:attr/selectableItemBackground"
android:background="#FFFFFF"
tools:context=".DetailActivity">

<RelativeLayout
    android:id="@+id/view_background2"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    ...
</RelativeLayout>

<RelativeLayout
    android:id="@+id/view_foreground2"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:background="@color/colorFlLabelFinal"  >

        <androidx.cardview.widget.CardView
            android:id="@+id/cardview_dets"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            ...
} 

视图模型

...
LiveData<List<Card>> getSingleCard(int cardId) {
    return repository.getSingleCard(cardId);
}

存储库

...
 public LiveData<List<Card>> getSingleCard(int cardId) {
    return quickcardDao.getSingleCard(cardId);
}  

...
@Query("SELECT * FROM cards WHERE cardId = :cardId LIMIT 1")
LiveData<List<Card>> getSingleCard(int cardId);

【问题讨论】:

  • 在此处添加断点 if (extras != null) here if (classname != null && classname.equals("fromMain")) and here if (card != null)该卡为空。好像卡号的值没有被正确传递。
  • @hfarhanahmed DetailActivity 中的卡片永远不应为空,因为用户总是单击 MainActivity 中的卡片。我在 "card = card.getId()": "Toast.makeText(DetailActivity.this, "" + cardId, Toast.LENGTH_SHORT).show();" 之后使用此 Toast 确认 Room 数据库中的 cardId 值是正确的
  • ID 是正确的,仍然没有显示数据?
  • 是的。因此,我认为这一定是 ViewModel 及其观察者的问题。
  • adapter2.setCardList(singleAdapterList);分享一下这个功能的实现

标签: android-layout android-recyclerview android-cardview


【解决方案1】:

因此,如果数据没有改变,那么返回相同的 DetailActivity 将不会刷新视图。答案是在数据没有改变的情况下重新使用 LiveData(而不是从数据库中重新加载 LiveData)。有关解决我的问题的“loadUsers()”示例,请参阅 Android Developers Architecture Components guide for ViewModel,“实现 ViewModel”部分:https://developer.android.com/topic/libraries/architecture/viewmodel

【讨论】:

    猜你喜欢
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 2022-12-12
    • 1970-01-01
    相关资源
    最近更新 更多