title: Sending Data from Activity to Fragment Using Arguments (Kotlin/Android)
body: <p>I am trying to send data from an Activity to it's child fragment. I have one activity that first loads all the fragments like this: </p>
  
  <pre><code>    view_pager.adapter = TabsAdapter(supportFragmentManager)
      tab_layout.setupWithViewPager(view_pager)
  </code></pre>
  
  <p><code>TabsAdapter</code> here is just an if condition for a tab carousel that supports swiping and clicking tab headers to change tabs.</p>
  
  <p>After I load the tabs I call a Fuel http request to get weather data from <a href="https://openweathermap.org" rel="nofollow noreferrer">https://openweathermap.org</a>, a very simple API. I successfully retrieve my local weather and can log the output to the console. Where I am stuck is sending the data to the Fragment.</p>
  
  <p>There are a lot of stackoverflow answers to this question. My issue is that I need to do two things:</p>
  
  <p>1) send the data to the fragment, preferably using an argument as this looks simplest 
  and</p>
  
  <p>2) setting some textViews in my fragment to be the value of the weather (display "It's sunny!")</p>
  
  <p>Here is how I am attempting to solve the problem so far:</p>
  
  <p>In my activity, after the data comes back from the http request, I put the data in a bundle and send the bundle to a method inside my fragment class:</p>
  
  <pre><code> 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)
  </code></pre>
  
  <p>Here is the fragment I am working with. So in <code>onCreateView</code> I set the <code>weathermainView</code> and <code>weatherdescriptionView</code> to items that I have in the layout for the fragment. I have to do this in <code>onCreateView</code> because this is the only place where <code>view</code> is available. I have these as public variables because I need them accessible in my <code>getWeather</code> function. </p>
  
  <p>My <code>getWeather</code> function tries to take the bundle arguments and set them equal to the textViews, <strong>however</strong> no matter what I do <code>weathermainView</code> and <code>weatherdescriptionView</code> text values are null, and they do not show in my page in the emulator. I had originally thought that I was experiencing a race condition between creating the tab and getting the data in the activity, so I put in a timeout. However, this does not solve the problem either.</p>
  
  <p>Here is the fragment code: </p>
  
  <pre><code>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&lt;TextView&gt;(R.id.textWeatherMain)
          weatherdescriptionView = view.findViewById&lt;TextView&gt;(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)
  
      }
  }
  </code></pre>
  
  <p>Here is the command line output I'm seeing:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Note: <code>!!!after setting weathermainView in onCreateView!!!</code> is the first output, so the tabs must be instantiated before the response comes back from the http request and the <code>getWeather</code> call is made. <strong>And</strong> both setting the weather variables in the activity and <code>onCreateView</code> of fragment works. <strong>But</strong></p>
  
  <pre><code>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
  </code></pre>
  
  <p><strong>So why are these null?</strong></p>
  
  <p>There's no race condition, I can set in <code>onCreatView</code> successfully. I even put in a timeout. I'm very confused, any hints would help.</p>
  
  <p>EDIT: </p>
  
  <p>Here is my TabsAdapter: </p>
  
  <pre><code>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 -&gt; HomeFragment()
              1 -&gt; MusicFragment()
              2 -&gt; MapFragment()
              else -&gt; 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]
      }
  }
  </code></pre>