不调用 RecyclerView 函数

RecyclerView functions aren't called

我正在尝试在回收站视图中显示交易列表。
每笔交易都由约束布局内的 CardView 表示(参见 item_transaction.xml)。

不知何故,我的 RecyclerView 适配器(onCreateViewHolderonBindViewHoldergetItemCount)的功能从未被调用(从未显示日志- 我删除了其中的大部分以便代码更易于阅读)。 因此,RecyclerView 内容不会显示在我的应用程序上。

还值得指出的是,我的适配器中有一个名为 data 的事务列表。每当我在列表中设置数据时,它都会更新。没有问题。

I know notifyDataSetChanged() isn't clean, I'll change it later on when I manage to get everything working.

这是我想要的预览,以便您更好地理解这个想法:

EDIT : 我的片段显示正常并且执行代码没有问题。

等一下,因为有很多代码:

package com.example.manage.manageit.database

class Transaction(
    var value: Long = 0,
    var note: String = "",
    var budget: String = "",
    var creationTime: Long = System.currentTimeMillis()
)

Transaction.kt

package com.example.manage.manageit.home

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.manage.manageit.databinding.ActivityHomeBinding

import androidx.fragment.app.Fragment
import com.example.manage.manageit.R
import com.example.manage.manageit.about.AboutFragment
import com.example.manage.manageit.budget.TransactionFragment

class HomeActivity : AppCompatActivity() {
    private lateinit var binding: ActivityHomeBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_home)

        binding.bottomNavigation.menu.getItem(0).isCheckable = true
        setFragment(HomeFragment())

        binding.bottomNavigation.setOnItemSelectedListener {menu ->
            when(menu.itemId){

                R.id.homeFragmentButton -> {
                    setFragment(HomeFragment())
                    true
                }

                R.id.transactionFragmentButton -> {
                    setFragment(TransactionFragment())
                    true
                }

                R.id.aboutFragmentButton -> {
                    setFragment(AboutFragment())
                    true
                }

                else -> false
            }
        }

    }

    private fun setFragment(fr : Fragment){
        val frag = supportFragmentManager.beginTransaction()
        frag.replace(R.id.myNavHostFragment,fr)
        frag.commit()
    }
}

HomeActivity.kt : 它包含一个 BottomNavigationView 和我的片段。

package com.example.manage.manageit.home

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.manage.manageit.R
import com.example.manage.manageit.adapters.TransactionAdapter
import com.example.manage.manageit.database.Transaction
import com.example.manage.manageit.databinding.FragmentHomeBinding
import java.util.logging.Logger

class HomeFragment : Fragment() {
    private var logger = Logger.getLogger(HomeFragment::class.java.name)

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding: FragmentHomeBinding = DataBindingUtil.inflate(
            inflater,
            R.layout.fragment_home,
            container,
            false
        )

        val recyclerView: RecyclerView = binding.transactionList
        val transactionAdapter = TransactionAdapter()
        recyclerView.adapter = transactionAdapter
        recyclerView.layoutManager = LinearLayoutManager(context)

        transactionAdapter.data = listOf(
            Transaction(10, "Transaction note", "Groceries"),
            Transaction(20, "Transaction note", "Groceries"),
            Transaction(30, "Transaction note", "Groceries")
        )

        return inflater.inflate(R.layout.fragment_home, container, false)
    }
}

HomeFragment.kt

package com.example.manage.manageit.adapters

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.manage.manageit.R
import com.example.manage.manageit.database.Transaction
import java.util.logging.Logger

class TransactionAdapter : RecyclerView.Adapter<TransactionViewHolder>() {
    private var logger = Logger.getLogger(this::class.java.name)

    var data = listOf<Transaction>()
        set(value) {
            field = value
            notifyDataSetChanged()
        }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
        logger.info("adapter : onCreateViewHolder()")
        return TransactionViewHolder.from(parent)
    }

    override fun onBindViewHolder(holder: TransactionViewHolder, position: Int) {
        val item = this.data[position]
        holder.bind(item)
    }

    override fun getItemCount(): Int {
        logger.info("adapter : getItemCount()")
        return this.data.size
    }
}

class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val icon: ImageView = itemView.findViewById(R.id.transaction_icon)
    private val note: TextView = itemView.findViewById(R.id.transaction_note)
    private val value: TextView = itemView.findViewById(R.id.transaction_value)

    fun bind(item: Transaction) {
        icon.setImageResource(R.drawable.ic_dollar_sign)
        note.text = item.note
        value.text = item.value.toString()
    }

    companion object {
        fun from(parent: ViewGroup): TransactionViewHolder {
            val layoutInflater = LayoutInflater.from(parent.context)
            val view = layoutInflater
                .inflate(R.layout.item_transaction, parent, false)

            return TransactionViewHolder(view)
        }
    }
}

TransactionAdapter.kt

<?xml version="1.0" encoding="utf-8"?>
<layout 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"
    tools:context="com.example.manage.manageit.home.HomeActivity">

    <RelativeLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

            <androidx.fragment.app.FragmentContainerView
                android:id="@+id/myNavHostFragment"
                android:name="androidx.navigation.fragment.NavHostFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:defaultNavHost="true"/>
        </LinearLayout>

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="@android:color/black"
            android:paddingVertical="6dp"
            app:itemIconSize="28dp"
            app:itemIconTint="@color/nav_bar_item"
            app:itemRippleColor="@color/ripple_color"
            app:itemTextColor="@color/nav_bar_item"
            app:labelVisibilityMode="unlabeled"
            app:menu="@menu/bottom_navigation_menu" />

    </RelativeLayout>
</layout>

activity_home.xml

<?xml version="1.0" encoding="utf-8"?>

<layout 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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/black"
        android:fillViewport="true"
        tools:context="com.example.manage.manageit.home.HomeFragment">

        <TextView
            android:id="@+id/homeActivityTitle"
            style="@style/activityTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/medium_margin"
            android:layout_marginTop="@dimen/medium_margin"
            android:layout_marginEnd="@dimen/medium_margin"
            android:text="@string/home_text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/transaction_list"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:visibility="visible"
            app:layout_constraintBottom_toTopOf="@+id/floatingActionButton"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/homeActivityTitle" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/floatingActionButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="@dimen/medium_margin"
            android:layout_marginBottom="@dimen/very_big_margin"
            android:backgroundTint="@color/secondaryColor"
            android:clickable="true"
            android:contentDescription="@string/add_button_description"
            android:src="@drawable/ic_plus"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:maxImageSize="32dp"
            tools:ignore="RedundantDescriptionCheck" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

fragment_home.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <androidx.cardview.widget.CardView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="20dp"
        app:cardBackgroundColor="@android:color/transparent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="@drawable/transaction">

            <ImageView
                android:id="@+id/transaction_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="30dp"
                android:contentDescription="Icon"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:srcCompat="@drawable/ic_dollar_sign"
                app:tint="@android:color/white" />

            <TextView
                android:id="@+id/transaction_note"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="30dp"
                android:text="Transaction note"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toEndOf="@+id/transaction_icon"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/transaction_value"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="30dp"
                android:text="55€"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

item_transaction.xml:基本上是一个带有图像和两个文本视图(交易“注释”和价值)的卡片视图。

onCreateView 中,您已经创建了两次视图布局。您使用 DataBindingUtil 完成的第一个,就是您设置其 RecyclerView 的那个。但是然后你让整个布局返回到垃圾收集器,因为你使用 layoutInflater 和 return 创建了一个全新的布局,该布局位于 onCreateView.

的最后一行

从技术上讲,您无论如何都不应该在 onCreateView 中设置视图。它应该在 onViewCreated() 内完成,尽管我认为这没有太大区别。然而,由于 Fragment 提供了一个可以自动膨胀提供的布局 ID 的构造函数,我认为完全消除 onCreateView() 更干净,像这样:

class HomeFragment : Fragment(R.layout.fragment_home) {
    private var logger = Logger.getLogger(HomeFragment::class.java.name)

    override fun onViewCreated(
        view: View,
        savedInstanceState: Bundle?
    ) {
        val binding: FragmentHomeBinding = DataBindingUtil.bind(view)

        val recyclerView: RecyclerView = binding.transactionList
        val transactionAdapter = TransactionAdapter()
        recyclerView.adapter = transactionAdapter
        recyclerView.layoutManager = LinearLayoutManager(context)

        transactionAdapter.data = listOf(
            Transaction(10, "Transaction note", "Groceries"),
            Transaction(20, "Transaction note", "Groceries"),
            Transaction(30, "Transaction note", "Groceries")
        )
    }
}