将数据从碎片Kotlin中从活动传递到循环系统
作为我的一门课程的一部分,我需要显示一个根据所选品牌列出汽车型号的回收模型。我设法在活动中检索了品牌的ID。但是,当我想将其发送到包含RecyClerview的片段时,我会遇到错误。屏幕快照在下面。
显然,这是我在活动中的支持FragmentManager的来源,但我找不到解决方案。如果有人能帮助我,那就太好了。
谢谢
mainActivity2.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()
}
}
modèlefragment.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
)
mymodèlerecyClerviewAdapter
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 + "'"
}
}
}
fragment_modele_list.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" />
答案
我终于通过直接在活动中使用我的API而不经过片段,没有片段,没有使用捆绑包。
mainActivity2.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
)
modèlefragment.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)
}
}
}
}
As part of one of my courses I need to display a recyclerview listing the car models according to the selected brand. I manage to retrieve the id of the brand in my activity. However, when I want to send it to my fragment containing the recyclerview I get an error. The screenshot is below.
It's obviously coming from my supportFragmentManager in the activity but I can't find a solution. If anyone can help me that would be great.
Thank you
MainActivity2.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()
}
}
ModèleFragment.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
)
MyModèleRecyclerViewAdapter
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 + "'"
}
}
}
fragment_modele_list.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" />
ANSWER
I finally found a solution by using my API directly in the activity without going through the fragment and without using a bundle.
MainActivity2.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
)
ModèleFragment.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)
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您从JSON中解析身体响应时,错误在50行上,这可能为null。
请检查以下方法:
val body = wendesp.body?.string()
上设置一个断开点并检查其值。如果继续失败,请在评论中分享JSON响应,我将尝试为您提供帮助。
The error is on the line 50 exactly when you parse from Json the body response, which can be null.
Please check the following approach:
val body = response.body?.string()
and checking its values.If it continue failing, share the json response on the comments and I will try to help you.