android-fragments 将数据从活动传递到片段Kotlin中的recyclerview

dtcbnfnu  于 2022-11-14  发布在  Android
关注(0)|答案(1)|浏览(136)

作为我的一门课程的一部分,我需要显示一个recyclerview,根据所选的品牌列出汽车型号。我设法在我的activity中检索到了品牌的id。但是,当我想把它发送到包含recyclerview的片段时,我得到了一个错误。截图如下。
这显然是来自我的supportFragmentManager在活动中,但我无法找到一个解决方案。如果有人能帮助我,这将是伟大的。
谢谢你
The error

主要活动2.kt

package ca.ulaval.ima.tp3

import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import ca.ulaval.ima.tp3.databinding.ActivityMain2Binding

class MainActivity2 : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMain2Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMain2Binding.inflate(layoutInflater)
        setContentView(binding.root)

        val idMarque = intent.getStringExtra("idMarque")
        println(idMarque)
        val fragment = ModèleFragment()
        val bundle = Bundle()
        bundle.putString("idmarque", idMarque)
        fragment.arguments = bundle

        supportFragmentManager.beginTransaction().replace(R.id.recyclerView_main, fragment).commit()

        setSupportActionBar(binding.toolbar)

        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)
        supportActionBar!!.setDisplayHomeAsUpEnabled(true)
    }

    override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return super.onSupportNavigateUp()
    }
}

模块片段.kt

package ca.ulaval.ima.tp3

import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import kotlinx.android.synthetic.main.fragment_marque_list.*
import okhttp3.*
import java.io.IOException

/**
 * A fragment representing a list of Items.
 */
class ModèleFragment : Fragment(), OnModeleClickListener {

    private var columnCount = 1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        arguments?.let {
            columnCount = it.getInt(ARG_COLUMN_COUNT)
        }

        fetchJson()
    }

    fun fetchJson() {
        val data = arguments
        val idMarque = data?.get("idmarque")
        val url = "https://tp3.infomobile.app/api/v1/brand/"+idMarque.toString()+"/models"

        val request = Request.Builder().url(url).build()

        val lesmodeles = OkHttpClient()
        lesmodeles.newCall(request).enqueue(object: Callback {
            override fun onResponse(call: Call, response: Response) {
                val body = response.body?.string()
                val gson = GsonBuilder().create()
                val homeFeed = gson.fromJson(body, HomeFeedModele::class.java)
                activity?.runOnUiThread {
                    recyclerView_main.adapter = MyModèleRecyclerViewAdapter(homeFeed)
                }
            }

            override fun onFailure(call: Call, e: IOException) {
                println("Failed to execute request")
            }
        })
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_modele_list, container, false)

        // Set the adapter
        if (view is RecyclerView) {
            with(view) {
                layoutManager = when {
                    columnCount <= 1 -> LinearLayoutManager(context)
                    else -> GridLayoutManager(context, columnCount)
                }
                //adapter = MyModèleRecyclerViewAdapter(listeDesVoitures)
            }
        }
        return view
    }

    override fun onModeleItemClicked(position: Int) {
        Toast.makeText(this.context, "ça marche", Toast.LENGTH_LONG).show()
        val intent = Intent(this@ModèleFragment.requireContext(),MainActivity3::class.java)
        startActivity(intent)
    }

    companion object {

        // TODO: Customize parameter argument names
        const val ARG_COLUMN_COUNT = "column-count"

        // TODO: Customize parameter initialization
        @JvmStatic
        fun newInstance(columnCount: Int) =
            ModèleFragment().apply {
                arguments = Bundle().apply {
                    putInt(ARG_COLUMN_COUNT, columnCount)
                }
            }
    }
}

class HomeFeedModele(
    @SerializedName("content")
    val modeles: List<Modele>
)

class Modele(
    @SerializedName("id")
    val id: Int,
    @SerializedName("name")
    val name: String
)

我的模块回收视图适配器

package ca.ulaval.ima.tp3

import android.content.Intent
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView

import ca.ulaval.ima.tp3.placeholder.PlaceholderContent.PlaceholderItem
import ca.ulaval.ima.tp3.databinding.FragmentModeleBinding

/**
 * [RecyclerView.Adapter] that can display a [PlaceholderItem].
 * TODO: Replace the implementation with code for your data type.
 */
class MyModèleRecyclerViewAdapter(val homeFeedModele: HomeFeedModele?
) : RecyclerView.Adapter<MyModèleRecyclerViewAdapter.ViewHolder>() {

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

        return ViewHolder(
            FragmentModeleBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )

    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = homeFeedModele?.modeles?.get(position)
        val leModele = item?.name.toString()
        holder.contentView.text = leModele
        holder.contentView.setOnClickListener{
            val context=holder.contentView.context
            val intent = Intent( context, MainActivity3::class.java)
            intent.putExtra("idModele", item?.id)
            context.startActivity(intent)
        }
    }

    override fun getItemCount(): Int {
        return homeFeedModele?.modeles?.size ?: 0
    }

    inner class ViewHolder(binding: FragmentModeleBinding) : RecyclerView.ViewHolder(binding.root) {
        val contentView: TextView = binding.content

        override fun toString(): String {
            return super.toString() + " '" + contentView.text + "'"
        }
    }

}

片段模型列表.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView 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/recyclerView_main"
    android:name="ca.ulaval.ima.tp3.ModèleFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    app:layoutManager="LinearLayoutManager"
    tools:context=".ModèleFragment"
    tools:listitem="@layout/fragment_modele" />

回答

我最终找到了一个解决方案,直接在Activity中使用我的API,而不需要遍历片段,也不需要使用bundle。

主要活动2.kt

package ca.ulaval.ima.tp3

import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import ca.ulaval.ima.tp3.databinding.ActivityMain2Binding
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import kotlinx.android.synthetic.main.fragment_marque_list.*
import okhttp3.*
import java.io.IOException

class MainActivity2 : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMain2Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMain2Binding.inflate(layoutInflater)
        setContentView(binding.root)

        fetchJson()

        setSupportActionBar(binding.toolbar)

        val navController = findNavController(R.id.nav_host_fragment_content_main)
        appBarConfiguration = AppBarConfiguration(navController.graph)
        setupActionBarWithNavController(navController, appBarConfiguration)
        supportActionBar!!.setDisplayHomeAsUpEnabled(true)
    }

    fun fetchJson() {
        //val data = arguments
        val idMarque = intent.getStringExtra("idMarque")
        println("id de la marque" + idMarque)
        val url = "https://tp3.infomobile.app/api/v1/brand/"+idMarque.toString()+"/models"

        val request = Request.Builder().url(url).build()

        val lesmodeles = OkHttpClient()
        lesmodeles.newCall(request).enqueue(object: Callback {
            override fun onResponse(call: Call, response: Response) {
                val body = response.body?.string()
                val gson = GsonBuilder().create()
                val homeFeed = gson.fromJson(body, HomeFeedModele::class.java)
                runOnUiThread {
                    recyclerView_main.adapter = MyModèleRecyclerViewAdapter(homeFeed)
                }
            }

            override fun onFailure(call: Call, e: IOException) {
                println("Failed to execute request")
            }
        })
    }

    override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return super.onSupportNavigateUp()
    }
}


class HomeFeedModele(
    @SerializedName("content")
    val modeles: List<Modele>
)

class Modele(
    @SerializedName("id")
    val id: Int,
    @SerializedName("name")
    val name: String
)

模块片段.kt

package ca.ulaval.ima.tp3

import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import kotlinx.android.synthetic.main.fragment_marque_list.*
import okhttp3.*
import java.io.IOException

/**
 * A fragment representing a list of Items.
 */
class ModèleFragment : Fragment(), OnModeleClickListener {

    private var columnCount = 1

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        arguments?.let {
            columnCount = it.getInt(ARG_COLUMN_COUNT)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_modele_list, container, false)

        // Set the adapter
        if (view is RecyclerView) {
            with(view) {
                layoutManager = when {
                    columnCount <= 1 -> LinearLayoutManager(context)
                    else -> GridLayoutManager(context, columnCount)
                }
                //adapter = MyModèleRecyclerViewAdapter(listeDesVoitures)
            }
        }
        return view
    }

    override fun onModeleItemClicked(position: Int) {
        Toast.makeText(this.context, "ça marche", Toast.LENGTH_LONG).show()
        val intent = Intent(this@ModèleFragment.requireContext(),MainActivity3::class.java)
        startActivity(intent)
    }

    companion object {

        // TODO: Customize parameter argument names
        const val ARG_COLUMN_COUNT = "column-count"

        // TODO: Customize parameter initialization
        @JvmStatic
        fun newInstance(columnCount: Int) =
            ModèleFragment().apply {
                arguments = Bundle().apply {
                    putInt(ARG_COLUMN_COUNT, columnCount)
                }
            }
    }
}
mv1qrgav

mv1qrgav1#

当你从Json解析body响应时,错误就在第50行,它可以是空的。请检查以下方法:

  • 检查body不为空,其值也不为空,您可以在val body = response.body?.string()上设置一个断点并检查其值。
  • 我看到HomeFeedModele(瓦尔模型:列表)的所有值都不可为空,请检查您在该json响应上接收到的值是否从不为空,如果为空,请使这些值可为空并将其初始化为空。

如果它继续失败,请在评论中分享json的回应,我会尽力帮助你。

相关问题