【问题标题】:Recyclerview dataset does not change on fragment startRecyclerview 数据集在片段开始时不会改变
【发布时间】:2021-09-26 09:33:04
【问题描述】:

我的片段上有一个 RecyclerView,它从名为 Datasource 的对象中的 ArrayList 获取数据。我想在 Fragment 启动时从 Cloud Firestore 获取新项目,所以我创建了一个名为 getAllProducts 的函数,但是我只能在单击底部导航栏时获取项目。

我几乎尝试了另一个问题的所有答案。我尝试在 onCreate 上重新加载片段,我创建了一个导航动作来片段本身,我在 RecyclerView 适配器中添加了一个从 getAllProducts 函数和 notifyDataSetChanged() 获取数据的函数。我让 getAllProduct 返回数组列表并将其用作 RecyclerView 中的数据。他们都没有工作。

应用启动时:

点击主页时:

这里有相关代码

ProductAdapter.kt

class ProductAdapter(private val productList: ArrayList<ProductItem>):RecyclerView.Adapter<ProductViewHolder>() {

    inner class ProductViewHolder(itemView:View):RecyclerView.ViewHolder(itemView){
        val productImage: ImageView = itemView.findViewById(R.id.productPhoto)
        val productName: TextView = itemView.findViewById(R.id.productName)
        val productRatingBar: RatingBar = itemView.findViewById(R.id.ratingBar2)
        val productRating: TextView = itemView.findViewById(R.id.ratingint)
        val storeName: TextView = itemView.findViewById(R.id.productStoreName)
        val productPrice: TextView = itemView.findViewById(R.id.productPrice)

    }



    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {

        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.product_item,
        parent,false)

        return ProductViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
        val currentItem = productList[position]
        holder.itemView.setOnClickListener {
                view ->
            val action = ProductFragmentDirections.actionProductFragmentToParticularProductFragment2(currentItem)
            view.findNavController().navigate(action)
        }
        holder.productImage.setImageResource(currentItem.productImageResource)
        holder.productName.text = currentItem.productName
        holder.productRatingBar.rating = currentItem.productRating.toFloat()
        holder.productRating.text = currentItem.productRating.toString()
        holder.storeName.text = currentItem.storeName
        holder.productPrice.text = currentItem.productPrice.toString().plus("$")

    }


    override fun getItemCount() = productList.size
}

数据源.kt

object Datasource {

    var productList = arrayListOf(

        ProductItem(R.drawable.attach_money,"Sahibinden aerator",4.5,"Serhat Yilmaz",8),
        ProductItem(R.drawable.email,"dus kitapları",3.0,"nerhat Yilmaz",9),
        ProductItem(R.drawable.passwordicon,"h files",1.5,"berhat Yilmaz",77),
        ProductItem(R.drawable.category,"piyasemen",5.0,"xerhat Yilmaz",55),
        ProductItem(R.drawable.attach_money,"Sahibinden sasfaf",1.5,"kerhat Yilmaz",11),
        ProductItem(R.drawable.email,"tus kitapları",3.0,"uerhat Yilmaz",21),
        ProductItem(R.drawable.passwordicon,"f files",1.5,"yerhat Yilmaz",47),
        ProductItem(R.drawable.category,"anguldruva",2.0,"terhat Yilmaz",35),
        ProductItem(R.drawable.email,"tus2 kitaplarım",3.0,"werhat Yilmaz",78),
        ProductItem(R.drawable.passwordicon,"endobox",2.5,"Zerhat Yilmaz",95),
        ProductItem(R.drawable.category,"basplak",4.0,"Ferhat Yilmaz",12)

    )

    fun loadProduct(): ArrayList<ProductItem>{
        return productList
    }
}

ProductFragment.kt

class ProductFragment : Fragment() {
    private val myDataset = Datasource.productList
    private val adapter = ProductAdapter(myDataset)



    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {


        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.products_fragment, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)


        val recyclerView: RecyclerView = view.findViewById(R.id.recycler_product)
        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(requireActivity())
        FireStoreClass().getAllProducts()
        adapter.notifyDataSetChanged()

    }



}

FireStoreClass().getAllProducts()

private val mFireStore = FirebaseFirestore.getInstance()

fun getAllProducts() {


    mFireStore.collection(Constants.PRODUCTS)
        .get()
        .addOnSuccessListener {
            documents ->
            val list = arrayListOf<ProductItem>()
            for (document in documents){

                val product = document.toObject(ProductItem::class.java)
                list.add(product)

            }
            Datasource.productList = list
            }
        .addOnFailureListener {
            //Toast.makeText(activity, "Can not get Product! ${it.message}", Toast.LENGTH_SHORT).show()
        }

}

如果您需要查看:

NavigateActivity.kt

class NavigateActivity : AppCompatActivity() {
    private lateinit var navController: NavController
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_navigate)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        navController = navHostFragment.findNavController()
        val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavView)
        bottomNavigationView.setupWithNavController(navController)
        //val action = HomeFragmentDirections


    }


}

mobile_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/mobile_navigation"
    app:startDestination="@id/product_Fragment">

    <fragment
        android:id="@+id/product_Fragment"
        android:name="com.example.TheDentalSupplies.fragments.ProductFragment"
        android:label="products_fragment"
        tools:layout="@layout/products_fragment" >

        <action
            android:id="@+id/action_productFragment_to_particularProductFragment2"
            app:destination="@id/particularProductFragment" />

        <action
            android:id="@+id/action_productFragment_Reload"
            app:destination="@id/product_Fragment" />



    </fragment>
    <fragment
        android:id="@+id/addPostNavActivity"
        android:name="com.example.TheDentalSupplies.AddActivity"
        android:label="addpost"
        tools:layout="@layout/addpost" >
        <action
            android:id="@+id/action_addPostNavActivity_to_productFragment"
            app:destination="@id/product_Fragment" />
    </fragment>

    <activity
        android:id="@+id/userActivity"
        android:name="com.example.TheDentalSupplies.UserActivity"
        android:label="userlayout"
        tools:layout="@layout/userlayout" />
    <fragment
        android:id="@+id/bucketFragment"
        android:name="com.example.TheDentalSupplies.fragments.BucketFragment"
        android:label="bucketlayout"
        tools:layout="@layout/bucketlayout" />
    <fragment
        android:id="@+id/particularProductFragment"
        android:name="com.example.TheDentalSupplies.fragments.ParticularProductFragment"
        android:label="product_layout"
        tools:layout="@layout/product_layout">
        <argument
            android:name="navProductItem"
            app:argType="com.example.TheDentalSupplies.models.ProductItem" />
        <action
            android:id="@+id/action_to_bucketFragment"
            app:destination="@id/bucketFragment" />
        <action
            android:id="@+id/action_to_messageActivity"
            app:destination="@id/messageActivity" />
        <action
            android:id="@+id/action_feedbacksFragment2"
            app:destination="@id/feedbacksFragment2" />
    </fragment>
    <activity
        android:id="@+id/messageActivity"
        android:name="com.example.TheDentalSupplies.MessageActivity"
        android:label="messagelayout"
        tools:layout="@layout/messagelayout" />
    <fragment
        android:id="@+id/feedbacksFragment2"
        android:name="com.example.TheDentalSupplies.fragments.FeedbacksFragment"
        android:label="feedbacks_layout"
        tools:layout="@layout/feedbacks_layout" />

</navigation>

【问题讨论】:

    标签: android firebase kotlin google-cloud-firestore android-recyclerview


    【解决方案1】:

    Firebase API 是异步的。因此,任何需要来自数据库的数据的代码都需要在 onSuccess() 方法中,或者从那里调用。在此方法中分配list 对象:

    Datasource.productList = list
    

    并不意味着它会立即分配它。数据加载完成后调用 getAllProducts() 方法后始终会触发此代码。因此,您拥有的最佳选择是像这样创建以下对象:

    private val myDataset = Datasource.productList
    private val adapter = ProductAdapter(myDataset)
    

    onViewCreated里面:

    val recyclerView: RecyclerView = view.findViewById(R.id.recycler_product)
    recyclerView.layoutManager = LinearLayoutManager(requireActivity())
    recyclerView.adapter = adapter
    FireStoreClass().getAllProducts()
    

    在 getAllProducts() 方法中,只需执行以下操作:

    fun getAllProducts() {
        mFireStore.collection(Constants.PRODUCTS)
            .get()
            .addOnSuccessListener { documents ->
                for (document in documents){
                    val product = document.toObject(ProductItem::class.java)
                    myDataset.add(product)
    
                }
                adapter.notifyDataSetChanged()
            }.addOnFailureListener {
                Toast.makeText(activity, "Can not get Product! ${it.message}", Toast.LENGTH_SHORT).show()
            }
    
    }
    

    这意味着只有当您从数据库中获得所有必要的数据时才通知适配器。

    由于您使用的是 Kotlin,我想您可能也对这篇文章感兴趣:

    【讨论】:

    • 非常感谢您的回答。但它仍然不会在应用启动时加载产品。我应该在哪里添加 FireStoreClass().getAllProducts() ?由于我的英语不太好,希望我没有错过您的回答。
    • 哦,对不起,我的错。只是忘了添加 FireStoreClass().getAllProducts() 。请检查我更新的答案。顺便说一句,你的英语真的很好;)
    • 不幸的是它没有工作。应用程序启动时仍然不加载,我不知道为什么。感谢您的回答。祝你有美好的一天:)
    • “它不起作用”没有提供足够的信息,所以我可以进一步帮助您。 onFailure 中的 Toast 消息是否显示了什么?您是否尝试将 onViewCreated 上的四行代码移至 onCreateView 内?是这样的吗?
    • 当我向 onCreateView 添加四行时,我得到了这个错误 java.lang.IllegalStateException: Fragment ProductFragment{1336db9} (0bd85290-7fbe-4464-89cf-046e81c43e07 id=0x7f0a0162) did not return a View来自 onCreateView() 或在 onCreateView() 之前调用。
    【解决方案2】:

    我终于找到了一种方法,虽然不是最好的解决方案,但却能胜任。

    常量.kt

    object Constants {
        var REPEAT:Int = 0}
    

    在 ProductFragment.kt 中

    if (Constants.REPEAT < 1){
                Constants.REPEAT = Constants.REPEAT + 1
                Handler(Looper.getMainLooper()).postDelayed({
                    Toast.makeText(requireContext(),"got here", Toast.LENGTH_SHORT).show()
                    val bottom = view.findNavController()
                    bottom.navigate(R.id.action_product_Fragment_self)
                },5000)
            }
    

    【讨论】:

    • 将操作延迟 5000 毫秒根本不是解决方案。用 5001 毫秒读取数据怎么样?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多