java.lang.IllegalArgumentException:缺少必需的参数"data"并且没有android:defaultValue



我试图将数据从API上的recycleView on Home Activity传递到新的活动和片段,但我遇到了类似于此的问题

java.lang.IllegalArgumentException: Required argument "data" is missing and does not have an android:defaultValue
at com.project.icacraft.ui.detail.DetailFragmentArgs$Companion.fromBundle(DetailFragmentArgs.kt:60)
at com.project.icacraft.ui.detail.DetailFragment.onActivityCreated(DetailFragment.kt:35)

我有两个可回收视图,水平和垂直,这是我的HomeAdapter代码:

class HomeAdapter (
private val listData: List<Data>,
private val itemAdapterCallback: ItemAdapterCallback
) : RecyclerView.Adapter<HomeAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.item_home_horizontal, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(listData[position], itemAdapterCallback)
}
override fun getItemCount(): Int {
return listData.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(data: Data, itemAdapterCallback: ItemAdapterCallback) {
itemView.apply {
tvTitle.text = data.name
rbcraft.rating = data.rate?.toFloat()?:0f
Glide.with(context)
.load(data.picturePath)
.into(ivPoster)
itemView.setOnClickListener { view -> itemAdapterCallback.onClick(view, data) }
}
}
}
interface ItemAdapterCallback {
fun onClick(v: View?, data: Data)
}
}

主页演示者:

class HomePresenter (private val view:HomeContract.View) : HomeContract.Presenter{
private val mCompositeDisposable : CompositeDisposable?
init {
this.mCompositeDisposable = CompositeDisposable()
}
override fun getHome() {
view.showLoading()
val disposable = HttpClient.getInstance().getAPI()!!.home()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
view.dismissLoading()
if (it.meta?.status.equals("success")){
it.data?.let { data -> view.onHomeSuccess(data) }
} else {
view.onHomeFailed(it.meta?.message.toString())
}
},
{
view.dismissLoading()
view.onHomeFailed(it.getErrorBodyMessage())
}
)
mCompositeDisposable!!.add(disposable)
}
override fun subscribe() {}
override fun unSubscribe() {
mCompositeDisposable!!.clear()
}
}

以下是主页上Horizontal Recycleview的代码:

class HomeFragment : Fragment(), HomeAdapter.ItemAdapterCallback, HomeContract.View {
private var adapter: HomeAdapter? = null
var progressDialog: Dialog? = null
private var newStateList: ArrayList<Data>? = ArrayList()
private var popularList: ArrayList<Data>? = ArrayList()
private var recomendedList: ArrayList<Data>? = ArrayList()
private lateinit var presenter: HomePresenter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initView()
presenter = HomePresenter(this)
presenter.getHome()
}

private fun initView() {
progressDialog = Dialog(requireContext())
val dialogLayout = layoutInflater.inflate(R.layout.dialog_loader, null)
progressDialog?.let {
it.setContentView(dialogLayout)
it.setCancelable(false)
it.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
//menampilakn foto user
var user = IcaCraft.getApp().getUser()
var userResponse = Gson().fromJson(user, User::class.java)
if (!userResponse.profile_photo_url.isNullOrEmpty()) {
Glide.with(requireActivity())
.load(userResponse.profile_photo_url)
.into(ivProfile)
}
}
override fun onClick(v: View?, data: Data) {
var bundle = Bundle()
bundle.putParcelable("data", data)
val detail = Intent(activity, DetailActivity::class.java).putExtras(bundle)
startActivity(detail)
}
override fun onHomeSuccess(homeResponse: HomeResponse) {
for (a in homeResponse.data.indices) {
var items: List<String> = homeResponse.data[a].types?.split(",") ?: ArrayList()
for (x in items.indices)
{
if (items[x].equals("new_craft", true)) {
newStateList?.add(homeResponse.data[a])
} else if (items[x].equals("recommended", true)) {
recomendedList?.add(homeResponse.data[a])
} else if (items[x].equals("popular", true)) {
popularList?.add(homeResponse.data[a])
}
}
}
adapter = HomeAdapter(homeResponse.data, this)
val layoutManager: RecyclerView.LayoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
rvList.layoutManager = layoutManager
rvList.adapter = adapter
val sectionsPagerAdapter = SectionsPagerAdapter(
childFragmentManager
)
sectionsPagerAdapter.setData(newStateList, popularList, recomendedList)
//        viewPager!!.offscreenPageLimit = 3
viewPager.adapter = sectionsPagerAdapter
tabLayout.setupWithViewPager(viewPager)
}
override fun onHomeFailed(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
}
override fun showLoading() {
progressDialog?.show()
}
override fun dismissLoading() {
progressDialog?.dismiss()
}
}

SectionPagerAdapter 的代码

class SectionsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(
fm
) {

var new_craft: ArrayList<Data>? = ArrayList()
var popular: ArrayList<Data>? = ArrayList()
var recommended: ArrayList<Data>? = ArrayList()
override fun getItem(position: Int): Fragment {
var fragment : Fragment
return when (position) {
0 -> {
fragment = HomeNewCraftFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", new_craft)
fragment.setArguments(bundle)
return fragment
}
1 -> {
fragment = HomePopularFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", popular)
fragment.setArguments(bundle)
return fragment
}
2 -> {
fragment = HomeRecommendedFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", recommended)
fragment.setArguments(bundle)
return fragment
}
else -> {
fragment = HomeNewCraftFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", new_craft)
fragment.setArguments(bundle)
return fragment
}
}
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> "New Craft"
1 -> "Popular"
2 -> "Recommended"
else -> null
}
}
override fun getCount(): Int {
return 3
}
fun setData(newStateListParms: ArrayList<Data>?, popularListParms: ArrayList<Data>?, recomendedListParms: ArrayList<Data>?) {
new_craft = newStateListParms
popular = popularListParms
recommended = recomendedListParms
}
}

以下是垂直回收视图适配器的代码:

class HomeNewCraftAdapter (
private val listData: ArrayList<Data>,
private val itemAdapterCallback : ItemAdapterCallback
) : RecyclerView.Adapter<HomeNewCraftAdapter.ViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.item_home_vertical, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(listData[position], itemAdapterCallback)
}
override fun getItemCount(): Int {
return listData.size
}
class ViewHolder (itemView:View) : RecyclerView.ViewHolder(itemView){
fun bind(data : Data, itemAdapterCallback: ItemAdapterCallback){
itemView.apply {
tvTitle.text = data.name
tvPrice.formatPrice(data?.price.toString())
rbCraft.rating = data.rate?.toFloat() ?: 0f
Glide.with(context)
.load(data.picturePath)
.into(ivPoster)
itemView.setOnClickListener { view -> itemAdapterCallback.onClick(view, data) }
}
}
}
interface ItemAdapterCallback {
fun onClick(v: View?, data:Data)
}
}

垂直回收可视碎片代码:

class HomeNewCraftFragment : Fragment(), HomeNewCraftAdapter.ItemAdapterCallback {
private var adapter: HomeNewCraftAdapter? = null
private var newcraftlist: java.util.ArrayList<Data>? = java.util.ArrayList()
private var test: String? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home_new_craft, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
newcraftlist = arguments?.getParcelableArrayList("data")
adapter = HomeNewCraftAdapter(newcraftlist!!, this)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(activity)
rcListNewCraft.layoutManager = layoutManager
rcListNewCraft.adapter = adapter
}
override fun onClick(v: View?, data: Data) {
val detail = Intent(activity, DetailActivity::class.java).putExtra("data", data)
startActivity(detail)
}
}

我想在这里传递详细活动的数据:

class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detail)
intent.extras?.let {
val navController = Navigation.findNavController(findViewById(R.id.detailHostFragment))
val bundle = Bundle()
bundle.putParcelable("data", it.get("data") as Parcelable?)
navController.setGraph(navController.graph, bundle)
}
}
fun toolbarPayment() {
toolbar.visibility = View.VISIBLE
toolbar.title = "Payment"
toolbar.subtitle = "You deserve better meal"
toolbar.navigationIcon = resources.getDrawable(R.drawable.arrow_back)
toolbar.setNavigationOnClickListener { onBackPressed() }
}
fun toolbarDetail() {
toolbar.visibility = View.GONE
}
}

和片段:

class DetailFragment : Fragment() {
var data:Data?= null
var bundle:Bundle?= null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_detail, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as DetailActivity?)!!.toolbarDetail()
arguments?.let {
DetailFragmentArgs.fromBundle(it).data.let {
initView(it)
}
}
btnOrderNow.setOnClickListener { view ->
Navigation.findNavController(view).navigate(R.id.action_fragmentDetail_to_fragmentPayment, bundle)
}
}
private fun initView(data: Data?) {
bundle = bundleOf("data" to data)
Glide.with(requireContext())
.load(data?.picturePath)
.into(ivPoster)
tvTitle.text = data?.name
tvDescription.text = data?.description
tvMaterials.text = data?.materials
//        tvTotal.formatPrice(data?.price.toString())
}
}

这是导航:

<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"
app:startDestination="@id/fragmentDetail"
android:id="@+id/nav_detail">
<fragment
android:id="@+id/fragmentDetail"
android:name="com.project.icacraft.ui.detail.DetailFragment"
tools:layout="@layout/fragment_detail">
<action
android:id="@+id/action_fragmentDetail_to_fragmentPayment"
app:destination="@id/fragmentPayment" />
<argument
android:name="data"
app:argType="com.project.icacraft.model.response.home.Data"
app:nullable="true" />
</fragment>

这里是activity_detail:的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent"
android:orientation="vertical"
tools:context=".ui.detail.DetailActivity">

//Menambahkan toolbar dan detail fragment
<include
android:id="@+id/include_toolbar"
layout="@layout/layout_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<fragment
android:id="@+id/detailHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_detail"
/>
</LinearLayout>

根据将数据传递到起始目的地文档:

注意:当使用参数手动调用setGraph()时,在XML中创建NavHostFragment时,必须不要使用app:navGraph属性,因为将在内部调用setGraph()而不使用任何参数,从而导致图形和起始目标被创建两次。

因此,您可以通过从activity_detail.xml文件中删除app:navGraph="@navigation/nav_detail"行来修复错误。

您还需要更改setGraph调用以使用相同的R.navigation.nav_detail:

navController.setGraph(R.navigation.nav_detail, bundle)

最新更新