【发布时间】:2018-02-20 18:34:20
【问题描述】:
我正在尝试将数据从 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 中,我将weathermainView 和weatherdescriptionView 设置为片段布局中的项目。我必须在onCreateView 中执行此操作,因为这是唯一可以使用view 的地方。我将这些作为公共变量,因为我需要在我的getWeather 函数中访问它们。
我的getWeather 函数尝试获取捆绑参数并将它们设置为等于 textViews,然而无论我做什么,weathermainView 和 weatherdescriptionView 文本值都是空的,它们确实如此不显示在我的模拟器页面中。我原本以为我在创建选项卡和在活动中获取数据之间遇到了竞争条件,所以我设置了一个超时。但是,这也不能解决问题。
这里是片段代码:
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]
}
}
【问题讨论】:
-
在
onActivityCreated或onViewCreated中写入bundle 相关代码,您可能不会收到错误消息。如果有效,请更新.. -
嗯....不知道我知道怎么做。我尝试从这样的活动中传递参数:`homeFrag.arguments.putString(someweatherstring)
. InonViewCreated` 我有val weatherurl = arguments.getString("weatherurl"),但这给出了错误java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference。片段中的arguments应该是什么修饰符? -
首先你需要得到像
getArguments()这样的参数 -
记住,这是在 Kotlin 中,所以 get/setArguments() 现在是参数。它的语法略有不同。
-
我也有类似的问题。你的解决了吗?你能分享一下出了什么问题吗?
标签: java android android-fragments kotlin race-condition