簡體   English   中英

使用參數將數據從 Activity 發送到 Fragment (Kotlin/Android)

[英]Sending Data from Activity to Fragment Using Arguments (Kotlin/Android)

我正在嘗試將數據從 Activity 發送到它的子片段。 我有一個活動,它首先像這樣加載所有片段:

    view_pager.adapter = TabsAdapter(supportFragmentManager)
    tab_layout.setupWithViewPager(view_pager)

這里的TabsAdapter只是支持滑動和單擊選項卡標題以更改選項卡的選項卡輪播的 if 條件。

加載選項卡后,我調用 Fuel http 請求從https://openweathermap.org獲取天氣數據,這是一個非常簡單的 API。 我成功檢索了我當地的天氣,並且可以將輸出記錄到控制台。 我被卡住的地方是將數據發送到 Fragment。

這個問題有很多stackoverflow的答案。 我的問題是我需要做兩件事:

1) 將數據發送到片段,最好使用參數,因為這看起來最簡單

2)在我的片段中設置一些 textViews 作為天氣的值(顯示“天氣晴朗!”)

到目前為止,這是我嘗試解決問題的方法:

在我的活動中,數據從 http 請求返回后,我將數據放入一個包中,並將該包發送到片段類中的一個方法:

 println("success from json request to weatherAPI")
 val weatherArray = result.get().obj().getJSONArray("weather").get(0) as JSONObject
 println("value of main in weatherArray:" + weatherArray["main"])
 println("value of description in weatherArray:" + weatherArray["description"])
 println("value of icon in weatherArray: " + weatherArray["icon"])

 val args = Bundle()
 args.putString("weatherurl",  "http://openweathermap.org/img/w/"+weatherArray["icon"]+".png")
 args.putString("weatherdescription", weatherArray["description"].toString())
 args.putString("weathermain", weatherArray["main"].toString())

 val homeFrag = HomeFragment()
 homeFrag.getWeather(args)

這是我正在使用的片段。 因此,在onCreateView我將weathermainViewweatherdescriptionView設置為片段布局中的項目。 我必須在onCreateView執行此操作,因為這是唯一可用view地方。 我將這些作為公共變量,因為我需要在我的getWeather函數中訪問它們。

我的getWeather函數嘗試獲取 bundle 參數並將它們設置為等於weatherdescriptionView但是無論我做什么, weathermainViewweatherdescriptionView文本值都是空的,並且它們不會顯示在我的模擬器頁面中。 我原本以為我在創建選項卡和在活動中獲取數據之間遇到了競爭條件,所以我設置了超時。 然而,這也不能解決問題。

這是片段代碼:

class HomeFragment : Fragment() {
     var weathermainView: TextView?=null
     var weatherdescriptionView:  TextView?=null

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

        val view = inflater!!.inflate(R.layout.fragment_home, container, false)

        weathermainView = view.findViewById<TextView>(R.id.textWeatherMain)
        weatherdescriptionView = view.findViewById<TextView>(R.id.textWeatherDescription)
        println("!!!after setting weathermainView in onCreateView!!!")
        println("value of weathermainView " + weathermainView?.text.toString())

        return inflater!!.inflate(R.layout.fragment_home, container, false)
    }

    fun getWeather(args: Bundle){
        val weatherMain = args.getString("weathermain")
        val weatherDescription = args.getString("weatherdescription")
        val timer = Timer()
        timer.schedule(timerTask {
            println("value of weathermainView BEFORE SETTING" + weathermainView?.text.toString())
            println("value of weatherdescriptionView BEFORE SETTING" + weatherdescriptionView?.text.toString())
            weathermainView?.text =  args.getString("weathermain")
            weatherdescriptionView?.text = args.getString("weatherdescription")
            println("value of weathermainView " + weathermainView?.text.toString())
            println("value of weatherdescriptionView " + weatherdescriptionView?.text.toString())
        }, 10000)

        println("Value of weatherMain: " + weatherMain)
        println("Value of weatherDescription: " + weatherDescription)

    }
}

這是我看到的命令行輸出:

I/System.out: !!!after setting weathermainView in onCreateView!!!
I/System.out: value of weathermainView hello there home fragment
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/OpenGLRenderer: Swap behavior 0
D/EGL_emulation: eglCreateContext: 0x9ab28d60: maj 3 min 0 rcv 3
D/EGL_emulation: eglMakeCurrent: 0x9ab28d60: ver 3 0 (tinfo 0x99bf5790)
E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
D/EGL_emulation: eglMakeCurrent: 0x9ab28d60: ver 3 0 (tinfo 0x99bf5790)
I/System.out: success from json request to weatherAPI
I/System.out: value of main in weatherArray:Rain
I/System.out: value of description in weatherArray:light rain
I/System.out: value of icon in weatherArray: 10d
I/System.out: Value of weatherMain: Rain
I/System.out: Value of weatherDescription: light rain
I/System.out: value of weathermainView BEFORE SETTING: null
I/System.out: value of weatherdescriptionView BEFORE SETTING: null
I/System.out: value of weathermainView null
I/System.out: value of weatherdescriptionView null

注意: !!!after setting weathermainView in onCreateView!!! 是第一個輸出,因此必須在響應從 http 請求返回並進行getWeather調用之前實例化選項卡。 並且在活動中設置天氣變量和片段的onCreateView都有效。

I/System.out: value of weathermainView BEFORE SETTING: null
I/System.out: value of weatherdescriptionView BEFORE SETTING: null
I/System.out: value of weathermainView null
I/System.out: value of weatherdescriptionView null

那么為什么這些是空的呢?

沒有競爭條件,我可以成功地在onCreatView設置。 我什至暫停了。 我很困惑,任何提示都會有所幫助。

編輯:

這是我的 TabsAdapter:

class TabsAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager) {
    // Title for tabs
    private val fragmentTitles = arrayOf("Home", "Music", "Map")
    // Return the Fragment associated with a specified position.
    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> HomeFragment()
            1 -> MusicFragment()
            2 -> MapFragment()
            else -> HomeFragment()
        }
    }
    // Return the number of views/fragments available.
    override fun getCount(): Int = 3 // in our case 3 fragments
    // Return title based on position
    override fun getPageTitle(position: Int): CharSequence {
        return fragmentTitles[position]
    }
}

代碼中的以下行為您提供了一個 HomeFragment 的新實例:

val homeFrag = HomeFragment()

此實例未附加到Activity因此無需執行onCreateView() 因此, TextView都是null

您希望在已經附加到TabLayoutFragment顯示新數據。 所以你需要在某個變量中保留一個句柄 - 讓我們稱之為homeFragment - 然后寫

homeFragment.getWeather(args);

查看您的TabsAdapter實現,我認為將args傳遞給 Adapter 也是一個好主意,因此 Adapter 可以將數據傳遞給HomeFragment以便下次顯示時使用。 為了實現這一點, HomeFragment需要一個靜態instance()方法,該方法將接受一個 Bundle 參數並返回一個HomeFragment實例。 然后你可以使用這個方法而不是構造函數。

這篇文章展示了如何在 Kotlin 中做到這一點。

暫無
暫無

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

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