未解决的参考:使用自定义 Parcelable 参数时:Jetpack 导航
Unresolved Reference: When Custom Parcelable Argument Used : Jetpack Navigation
这是我第一次使用 Jetpack Navigation 和 Safe args。使用自定义 Parcelable 作为传递给特定片段的参数时出现错误。
这是我在构建时遇到的错误:
com/bhardwaj/ui/FragmentUIDetails.kt: (34, 26): Unresolved reference: uIDetail
这就是我的 FragmentUIDetails 的样子:
class FragmentUIDetails : Fragment(), UIDetailListener {
private lateinit var viewModel: FragmentUIDetailsViewModel
private lateinit var sliderAdapter: ImageSliderAdapter
private lateinit var viewPager: ViewPager2
private lateinit var dotsIndicator: DotsIndicator
private lateinit var uiDetails: UI
private var itemList: ArrayList<Any> = arrayListOf()
private val args: FragmentUIDetailsArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
uiDetails = args.uIDetail
return inflater.inflate(R.layout.fragment_ui_detail, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewPager = view.findViewById(R.id.viewPager)
dotsIndicator = view.findViewById(R.id.dotsIndicator)
viewModel = ViewModelProvider(this).get(FragmentUIDetailsViewModel::class.java)
itemList.addAll(uiDetails.uiImages!!)
sliderAdapter = context?.let { ImageSliderAdapter(it, itemList) }!!
context?.let {
viewModel.loadNativeAd(it, sliderAdapter)
}
viewPager.adapter = sliderAdapter
dotsIndicator.setViewPager2(viewPager)
}
private fun showInfo() {
activity?.let {
AlertDialog.Builder(it).apply {
val dialogView =
requireActivity().layoutInflater.inflate(R.layout.dialog_ui_information, null)
val designer = dialogView.findViewById<TextView>(R.id.tvDesignerInfo)
val source = dialogView.findViewById<TextView>(R.id.tvSourceInfo)
designer.text =
String.format("%s: %s", getString(R.string.designer), uiDetails.author)
source.text =
String.format("%s: %s", getString(R.string.source), uiDetails.source)
setView(dialogView)
}.create().show()
}
}
override fun onUIListClick(view: View) {
when (view.id) {
R.id.ivInfo -> showInfo()
R.id.ivShareUI -> viewModel.shareLink(
uiDetails.downloadUrl.toString(),
requireActivity()
)
R.id.fabButton -> viewModel.download(
uiDetails.downloadUrl.toString(),
uiDetails.fileName!!,
requireContext()
)
}
}
}
这就是我的导航图 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/navigation_main"
app:startDestination="@id/fragmentAdobeXD">
<fragment
android:id="@+id/fragmentAdobeXD"
android:name="com.bhardwaj.ui.view.FragmentAdobeXD"
android:label="fragment_adobe_xd"
tools:layout="@layout/fragment_adobe_xd">
<action
android:id="@+id/action_fragmentAdobeXD_to_fragmentSearch"
app:destination="@id/fragmentSearch" />
<action
android:id="@+id/action_fragmentAdobeXD_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
</fragment>
<fragment
android:id="@+id/fragmentFigma"
android:name="com.bhardwaj.ui.view.FragmentFigma"
android:label="fragment_figma"
tools:layout="@layout/fragment_figma">
<action
android:id="@+id/action_fragmentFigma_to_fragmentSearch"
app:destination="@id/fragmentSearch" />
<action
android:id="@+id/action_fragmentFigma_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
</fragment>
<fragment
android:id="@+id/fragmentSketch"
android:name="com.bhardwaj.ui.view.FragmentSketch"
android:label="fragment_sketch"
tools:layout="@layout/fragment_sketch">
<action
android:id="@+id/action_fragmentSketch_to_fragmentSearch"
app:destination="@id/fragmentSearch" />
<action
android:id="@+id/action_fragmentSketch_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
</fragment>
<fragment
android:id="@+id/fragmentMore"
android:name="com.bhardwaj.ui.view.FragmentMore"
android:label="fragment_more"
tools:layout="@layout/fragment_more" />
<fragment
android:id="@+id/fragmentSearch"
android:name="com.bhardwaj.ui.view.FragmentSearch"
android:label="FragmentSearch">
<action
android:id="@+id/action_fragmentSearch_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
<argument
android:name="SearchDetail"
android:defaultValue="@null"
app:argType="com.bhardwaj.ui.models.UI"
app:nullable="true" />
</fragment>
<fragment
android:id="@+id/fragmentUIDetails"
android:name="com.bhardwaj.ui.view.FragmentUIDetails"
android:label="FragmentUIDetails">
<argument
android:name="UIDetail"
app:argType="com.bhardwaj.ui.models.UI" />
</fragment>
项目中添加的依赖项-
构建。 Gradle(项目)-
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
构建。 Gradle(模块)-
id("androidx.navigation.safeargs.kotlin")
id("kotlin-parcelize")
implementation "androidx.navigation:navigation-fragment-ktx:2.3.5"
implementation "androidx.navigation:navigation-ui-ktx:2.3.5"
这是我的数据 Class 的样子:
@Parcelize
class UI(
val imageUrl: String? = null,
val title: String? = null,
val author: String? = null,
val downloadUrl: String? = null,
val fileName: String? = null,
val source: String? = null,
val timeStamp: Long? = 0,
val category: String? = null,
val tag: List<String>? = null,
val uiImages: List<String>? = null
) : Parcelable
我都试过了:
- 从 androidx.navigation 切换到 android.arch.navigation
- 使缓存无效并重新启动。
- 重建项目。
更新
这就是 FragmentUIDetailsArgs Class 的样子:
public data class FragmentUIDetailsArgs(
public val UIDetail: UI
) : NavArgs {
@Suppress("CAST_NEVER_SUCCEEDS")
public fun toBundle(): Bundle {
val result = Bundle()
if (Parcelable::class.java.isAssignableFrom(UI::class.java)) {
result.putParcelable("UIDetail", this.UIDetail as Parcelable)
} else if (Serializable::class.java.isAssignableFrom(UI::class.java)) {
result.putSerializable("UIDetail", this.UIDetail as Serializable)
} else {
throw UnsupportedOperationException(UI::class.java.name +
" must implement Parcelable or Serializable or must be an Enum.")
}
return result
}
public companion object {
@JvmStatic
public fun fromBundle(bundle: Bundle): FragmentUIDetailsArgs {
bundle.setClassLoader(FragmentUIDetailsArgs::class.java.classLoader)
val __UIDetail : UI?
if (bundle.containsKey("UIDetail")) {
if (Parcelable::class.java.isAssignableFrom(UI::class.java) ||
Serializable::class.java.isAssignableFrom(UI::class.java)) {
__UIDetail = bundle.get("UIDetail") as UI?
} else {
throw UnsupportedOperationException(UI::class.java.name +
" must implement Parcelable or Serializable or must be an Enum.")
}
if (__UIDetail == null) {
throw IllegalArgumentException("Argument \"UIDetail\" is marked as non-null but was passed a null value.")
}
} else {
throw IllegalArgumentException("Required argument \"UIDetail\" is missing and does not have an android:defaultValue")
}
return FragmentUIDetailsArgs(__UIDetail)
}
}
}
我就是这样解决问题的:
问题出在 4.0 以上的 IDE 和 Arctic Fox 版本中,就我而言,因为默认情况下它不引用导航参数文件夹,所以我们需要对位置进行硬编码。
转到 Build.gradle(模块)并复制此 -
android {
...
sourceSets {
main {
java {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
...
}
不要在参数名称的第一个字母中使用大写字母。对我有用
但是,如果你想动用资本。把这个放到你的 gradle.module
android {
...
sourceSets {
main {
java {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
...
}
这是我第一次使用 Jetpack Navigation 和 Safe args。使用自定义 Parcelable 作为传递给特定片段的参数时出现错误。
这是我在构建时遇到的错误:
com/bhardwaj/ui/FragmentUIDetails.kt: (34, 26): Unresolved reference: uIDetail
这就是我的 FragmentUIDetails 的样子:
class FragmentUIDetails : Fragment(), UIDetailListener {
private lateinit var viewModel: FragmentUIDetailsViewModel
private lateinit var sliderAdapter: ImageSliderAdapter
private lateinit var viewPager: ViewPager2
private lateinit var dotsIndicator: DotsIndicator
private lateinit var uiDetails: UI
private var itemList: ArrayList<Any> = arrayListOf()
private val args: FragmentUIDetailsArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
uiDetails = args.uIDetail
return inflater.inflate(R.layout.fragment_ui_detail, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewPager = view.findViewById(R.id.viewPager)
dotsIndicator = view.findViewById(R.id.dotsIndicator)
viewModel = ViewModelProvider(this).get(FragmentUIDetailsViewModel::class.java)
itemList.addAll(uiDetails.uiImages!!)
sliderAdapter = context?.let { ImageSliderAdapter(it, itemList) }!!
context?.let {
viewModel.loadNativeAd(it, sliderAdapter)
}
viewPager.adapter = sliderAdapter
dotsIndicator.setViewPager2(viewPager)
}
private fun showInfo() {
activity?.let {
AlertDialog.Builder(it).apply {
val dialogView =
requireActivity().layoutInflater.inflate(R.layout.dialog_ui_information, null)
val designer = dialogView.findViewById<TextView>(R.id.tvDesignerInfo)
val source = dialogView.findViewById<TextView>(R.id.tvSourceInfo)
designer.text =
String.format("%s: %s", getString(R.string.designer), uiDetails.author)
source.text =
String.format("%s: %s", getString(R.string.source), uiDetails.source)
setView(dialogView)
}.create().show()
}
}
override fun onUIListClick(view: View) {
when (view.id) {
R.id.ivInfo -> showInfo()
R.id.ivShareUI -> viewModel.shareLink(
uiDetails.downloadUrl.toString(),
requireActivity()
)
R.id.fabButton -> viewModel.download(
uiDetails.downloadUrl.toString(),
uiDetails.fileName!!,
requireContext()
)
}
}
}
这就是我的导航图 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/navigation_main"
app:startDestination="@id/fragmentAdobeXD">
<fragment
android:id="@+id/fragmentAdobeXD"
android:name="com.bhardwaj.ui.view.FragmentAdobeXD"
android:label="fragment_adobe_xd"
tools:layout="@layout/fragment_adobe_xd">
<action
android:id="@+id/action_fragmentAdobeXD_to_fragmentSearch"
app:destination="@id/fragmentSearch" />
<action
android:id="@+id/action_fragmentAdobeXD_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
</fragment>
<fragment
android:id="@+id/fragmentFigma"
android:name="com.bhardwaj.ui.view.FragmentFigma"
android:label="fragment_figma"
tools:layout="@layout/fragment_figma">
<action
android:id="@+id/action_fragmentFigma_to_fragmentSearch"
app:destination="@id/fragmentSearch" />
<action
android:id="@+id/action_fragmentFigma_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
</fragment>
<fragment
android:id="@+id/fragmentSketch"
android:name="com.bhardwaj.ui.view.FragmentSketch"
android:label="fragment_sketch"
tools:layout="@layout/fragment_sketch">
<action
android:id="@+id/action_fragmentSketch_to_fragmentSearch"
app:destination="@id/fragmentSearch" />
<action
android:id="@+id/action_fragmentSketch_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
</fragment>
<fragment
android:id="@+id/fragmentMore"
android:name="com.bhardwaj.ui.view.FragmentMore"
android:label="fragment_more"
tools:layout="@layout/fragment_more" />
<fragment
android:id="@+id/fragmentSearch"
android:name="com.bhardwaj.ui.view.FragmentSearch"
android:label="FragmentSearch">
<action
android:id="@+id/action_fragmentSearch_to_fragmentUIDetails"
app:destination="@id/fragmentUIDetails" />
<argument
android:name="SearchDetail"
android:defaultValue="@null"
app:argType="com.bhardwaj.ui.models.UI"
app:nullable="true" />
</fragment>
<fragment
android:id="@+id/fragmentUIDetails"
android:name="com.bhardwaj.ui.view.FragmentUIDetails"
android:label="FragmentUIDetails">
<argument
android:name="UIDetail"
app:argType="com.bhardwaj.ui.models.UI" />
</fragment>
项目中添加的依赖项-
构建。 Gradle(项目)-
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
构建。 Gradle(模块)-
id("androidx.navigation.safeargs.kotlin")
id("kotlin-parcelize")
implementation "androidx.navigation:navigation-fragment-ktx:2.3.5"
implementation "androidx.navigation:navigation-ui-ktx:2.3.5"
这是我的数据 Class 的样子:
@Parcelize
class UI(
val imageUrl: String? = null,
val title: String? = null,
val author: String? = null,
val downloadUrl: String? = null,
val fileName: String? = null,
val source: String? = null,
val timeStamp: Long? = 0,
val category: String? = null,
val tag: List<String>? = null,
val uiImages: List<String>? = null
) : Parcelable
我都试过了:
- 从 androidx.navigation 切换到 android.arch.navigation
- 使缓存无效并重新启动。
- 重建项目。
更新
这就是 FragmentUIDetailsArgs Class 的样子:
public data class FragmentUIDetailsArgs(
public val UIDetail: UI
) : NavArgs {
@Suppress("CAST_NEVER_SUCCEEDS")
public fun toBundle(): Bundle {
val result = Bundle()
if (Parcelable::class.java.isAssignableFrom(UI::class.java)) {
result.putParcelable("UIDetail", this.UIDetail as Parcelable)
} else if (Serializable::class.java.isAssignableFrom(UI::class.java)) {
result.putSerializable("UIDetail", this.UIDetail as Serializable)
} else {
throw UnsupportedOperationException(UI::class.java.name +
" must implement Parcelable or Serializable or must be an Enum.")
}
return result
}
public companion object {
@JvmStatic
public fun fromBundle(bundle: Bundle): FragmentUIDetailsArgs {
bundle.setClassLoader(FragmentUIDetailsArgs::class.java.classLoader)
val __UIDetail : UI?
if (bundle.containsKey("UIDetail")) {
if (Parcelable::class.java.isAssignableFrom(UI::class.java) ||
Serializable::class.java.isAssignableFrom(UI::class.java)) {
__UIDetail = bundle.get("UIDetail") as UI?
} else {
throw UnsupportedOperationException(UI::class.java.name +
" must implement Parcelable or Serializable or must be an Enum.")
}
if (__UIDetail == null) {
throw IllegalArgumentException("Argument \"UIDetail\" is marked as non-null but was passed a null value.")
}
} else {
throw IllegalArgumentException("Required argument \"UIDetail\" is missing and does not have an android:defaultValue")
}
return FragmentUIDetailsArgs(__UIDetail)
}
}
}
我就是这样解决问题的:
问题出在 4.0 以上的 IDE 和 Arctic Fox 版本中,就我而言,因为默认情况下它不引用导航参数文件夹,所以我们需要对位置进行硬编码。
转到 Build.gradle(模块)并复制此 -
android {
...
sourceSets {
main {
java {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
...
}
不要在参数名称的第一个字母中使用大写字母。对我有用
但是,如果你想动用资本。把这个放到你的 gradle.module
android {
...
sourceSets {
main {
java {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
...
}