簡體   English   中英

Android Kotlin 從 Recyclerview 中單擊的項目中獲取數據並在片段之間傳遞

[英]Android Kotlin get data from a clicked item in Recyclerview and pass it between fragments

所以我有兩個數據類( OutletListDataClassProductListDataClass ),當前由兩個不同的片段( OutletListFragment.ktProductListFragment.kt ,直接連接在導航圖中)使用。

這兩個片段都是 RecyclerView。 我想從OutletListFragment.kt (包含在兩個數據類中)中的單擊項目中提取信息並將其傳遞給ProductListFragment.kt

這些是我在兩個片段中使用的數據類:

OutletListDataClass

data class OutletListPOJODataClasses(

    @SerializedName("data")
    @Expose
    var data: List<OutletListPOJODataClassesDataItem>? = null,

    @SerializedName("error")
    val error: OutletListDataClassError? = null
)



data class OutletListPOJODataClassesDataItem(
    @SerializedName("stk_prodcode")//Both data classes have this variable
    @Expose
    val stkProdcode: String? = null,

    @SerializedName("stk_allqty")
    @Expose
    val stkAllqty: Int? = null,

    @SerializedName("skt_lastupdate")
    @Expose
    val sktLastupdate: String? = null,

    @SerializedName("outlet_address")
    @Expose
    val outletAddress: String? = null,

    @SerializedName("outlet_name")
    @Expose
    val outletName: String? = null,

    @SerializedName("stk_outcode")
    @Expose
    val stkOutcode: String? = null
)

產品列表數據類

data class ProductListPOJODataClasses(

    @field:SerializedName("data")
    val data: List<ProductListPOJODataClassesDataItem?>? = null,

    @field:SerializedName("error")
    val error: ProductListDataClassError? = null
)

data class ProductListDataClassError(

    @field:SerializedName("msg")
    val msg: String? = null,

    @field:SerializedName("code")
    val code: Int? = null,

    @field:SerializedName("status")
    val status: Boolean? = null
)

data class ProductListPOJODataClassesDataItem(
    @field:SerializedName("stk_prodcode")  //Both data classes have this variable
    val stkProdcode: String? = null,

    @field:SerializedName("stk_allqty")
    val stkAllqty: Int? = null,

    @field:SerializedName("pro_saleprice")
    val proSaleprice: Int? = null,

    @field:SerializedName("skt_lastupdate")
    val sktLastupdate: String? = null,

    @field:SerializedName("stk_outcode")
    val stkOutcode: String? = null,

    @field:SerializedName("pro_name")
    val proName: String? = null
)

如您所見,這兩個數據類包含 sa.me 變量(StkOutcode)。 這就是我想要提取的(來自OutletListDataItem

這是當前OutletListFragment.kt的代碼片段:

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

    (activity as AppCompatActivity).supportActionBar?.title = "Product List"

    binding = DataBindingUtil.inflate(
        inflater,
        R.layout.fragment_product_stock_outlet_list,
        container,
        false
    )

    //Show Progressbar While loading data
    showProgressBar()

    //Apply layout manager
    binding.rvOutletList.layoutManager = LinearLayoutManager((activity as AppCompatActivity))

    //Fetch Outlet List Data
    fetchOutletListData()

    // Declare that this fragment has menu
    setHasOptionsMenu(true)

    // Set action bar title to "Outlet List"
    (activity as AppCompatActivity).supportActionBar?.title = "Outlet List"

    return binding.root
}

這是我為 OutletListFragment 創建的 recyclerview 適配器。 插座列表適配器

 class OutletListItemHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    fun bind(
        outlet: OutletListPOJODataClassesDataItem,
        clickListener: OutletListOnItemClickListener?
    ) {
        itemView.outletName.text = outlet.outletName

        itemView.setOnClickListener {
            clickListener?.onItemClicked(outlet)
        }
    }
}

class OutletListAdapter(private var outletList: OutletListPOJODataClasses, private val itemClickListener: OutletListOnItemClickListener)
: RecyclerView.Adapter<OutletListItemHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OutletListItemHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.outlet_list_item_layout, parent, false)
        return OutletListItemHolder(v)
    }

    override fun getItemCount(): Int = outletList.data!!.size

    override fun onBindViewHolder(holder: OutletListItemHolder, position: Int) {
        val outlet = outletList.data?.get(position)
        if (outlet != null) {
            holder.bind(outlet, itemClickListener)
        }
    }
}


interface OutletListOnItemClickListener{
    fun onItemClicked(outlet: OutletListPOJODataClassesDataItem)
}

如何從 OutletListFragment.kt 中的數據OutletListFragment.kt中獲取我想要的變量並將其傳遞給ProductListFragment.kt 如果有任何不清楚的地方,請告訴我。

編輯:

這是navigation.xml的片段:

<fragment
    android:id="@+id/productStockOutletList"
    android:name="com.example.switchingandroidappproject.mainFragments.ProductStockOutletListFragment"
    android:label="ProductStockOutletList" >
    <action
        android:id="@+id/action_productStockOutletList_to_productListFragment"
        app:destination="@id/productListFragment"
        app:enterAnim="@android:anim/slide_in_left"
        app:exitAnim="@android:anim/slide_out_right"
        app:popEnterAnim="@android:anim/slide_in_left"
        app:popExitAnim="@anim/slide_out_left" />
</fragment>

<fragment
    android:id="@+id/productListFragment"
    android:name="com.example.switchingandroidappproject.mainFragments.ProductListFragment"
    android:label="ProductListFragment" />

如果您使用的是 Jetpack Navigation(並且您指的是“導航圖”之類的東西,那么顯然您正在使用 Jetpack Navigation),那么要在導航目的地之間傳遞 arguments,您必須使用正確的arguments定義一個<action作為可打包數據的一些變體傳遞給另一個片段。

這是文檔中的示例:

 <action android:id="@+id/startMyFragment" app:destination="@+id/myFragment"> <argument android:name="myArg" app:argType="integer" android:defaultValue="1" /> </action>

所以在你的情況下,它應該像你需要類似的東西

<navigation ...>
    <action android:id="@+id/toProductListFragment"
        app:destination="@+id/productListFragment">
        <argument
            android:name="stkProdcode"
            app:argType="string" />
    </action>

顯然,這些東西只有在您還啟用了safeargs插件的情況下才有效(否則您必須自己“記住”這個密鑰,或者手動編寫NavDirections class,或者自己組合Bundle - 無論哪種方式,Jetpack Navigation 都希望您使用 Safeargs傳遞參數):

buildscript {
    dependencies {
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.2.2"

apply plugin: "androidx.navigation.safeargs.kotlin"

然后你應該能夠做到

class OutletListFragment: Fragment(), OutletListOnItemClickListener {
    ....

    override fun onItemClicked(outlet: OutletListPOJODataClassesDataItem) {
        Navigation.findNavController(view).navigate(NavigationDirections.toProductListFragment(outlet.stkProdcode))
    }
}

由於 Jetpack Navigation 的限制,您還必須將參數定義復制到<fragment標記中:

<fragment
    android:id="@+id/productListFragment"
    android:name="com.example.switchingandroidappproject.mainFragments.ProductListFragment"
    android:label="ProductListFragment" >
    <argument
        android:name="stkProdcode"
        app:argType="string" />
</fragment>

確保不要打錯字( android:name mismatch),因為你會遇到意外的失敗)。

現在您可以在另一邊獲得您的 arguments

val args = ProductListFragmentArgs.fromBundle(getArguments())
val code = args.stkProdcode

我並沒有真正使用 Jetpack Navigation,所以我很驚訝地看到您必須將片段 args 復制到動作 args,但是您已經有了。


...想想我用什么代替 Jetpack Navigation ,這很簡單

// send
backstack.goTo(ProductListScreen(stkProdCode))
// receive
val prodCode = getKey<ProductListScreen>().stkProdCode

並且是(如果不是更多的話)類型安全的。 *grumble* *grumble* 但這對你的情況沒有幫助,那不是 Jetpack Navigation。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM