Kotlin as a language is comfy though, barring the ...
# android
g
Kotlin as a language is comfy though, barring the Android bit.
m
Moving to a thread since you have a big question. I think you have over-engineered the dialog popup, but I don’t know all requirements so im not sure.
you can inherit from DialogFragment and just open it as a normal fragment instead of dealing with “window” objects directly.
g
I didn't engineer any of this at all, which is part of the problem (I have never even done Android development before). This app was outsourced to foreign developers before I came on to the company =/
Sorry for the long series of texts, I should have definitely put it in a thread on the first comment, my mistake.
👍 1
m
so you basically just want to add a new button opening the same dialog as you can open from another page as well?
g
Yeah, if you see the image, that pop-up screen on the bottom of the two screens is currently triggered from the join button on the left screen. I just need to trigger that from the new floating Join button on the right screen
m
where does the
joinGameButton()
function live? (in which class)
g
The function to trigger it is coded as a private method into
GameFragment
though. I tried making it public, doing
val gameFragment = GameFragment.newInstance()
inside of
DetailFragment
and then
gameFragment.joinGamePopup()
but it breaks because of
Dialog(context)
inside of the
joinGamePopup()
method in
GameFragment
where does the
joinGameButton()
function live? (in which class) 
GameFragment
m
does it use alot of other data from GameFragment, or could you extract it to a new class?
context is easy to pass in as an argument to the new class, but do you need anything else?
let me explain the problem. a fragment doesn’t actually have a context, the context is the activity that the fragment is attached to, so if you just create a new instance of a fragment and then try to get the context, you will get
null
g
So the arguments that it takes are an instance of
JoinGameModel
, which has some information about the game the player is trying to join, and
position
, which after several hours I figured out is a magic variable that gets passed into fragments denoting their index. I was able to recreate the
JoinGameModel
instance because it gets
gameData
from the parent fragment (GameFragment), and I tried hardcoding `0`/`1` as the
position
to try to trigger it on the first or second fragment.
m
so if you can extract the function to its own class, make sure that you pass JoinGameModel in as a parameter (from either screen that opens this dialog) and context as a second parameter, this should work nicely
g
It looks like
Dialog(context)
is where most of the stuff happens in that method. This seems to create the pop-up window and populate it with info. So assuming I can have the right
context
value in there, it should work right?
Yeah but what is
context
Copy code
class GamesFragment: Fragment(), SwipeRefreshLayout.OnRefreshListener{

    var context: MainActivity? = null
Copy code
private fun joinGamePopup(gameJoin: JoinGameModel,position:Int) {
            val dialog = Dialog(context)
Copy code
2020-03-11 13:22:50.418 26091-26091/com.plei.dev E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.plei.dev, PID: 26091
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
        at android.app.Dialog.<init>(Dialog.java:175)
        at android.app.Dialog.<init>(Dialog.java:149)
        at com.plei.screens.games.fragment.GamesFragment.joinGamePopup(GamesFragment.kt:246)
        at com.plei.screens.games.fragment.DetailFragment$_initialize$1.onClick(DetailFragment.kt:92)
m
context is and object in android that holds more or less all important stuff. It tells you the current theme, language, resourcefile pointers, screen measurements and what not. Application, Activity and Services has contexts (with minor differences) but fragments doesn’t so they have to get teh context form the outside (e.g Activity)
Copy code
joinGamePopup(context:Context, gameJoin: JoinGameModel,position:Int)
g
So I need to figure out how to get the context from the parent
GameFragment
into the
DetailFragment
function here to pass into context?
m
no, you should not try to pass contexts between fragments yourself. the OS will make sure you have a context in your fragment when its showing on the screen
refactor the method to take context as a parameter and move it to a separate class so you don’t have to instantiate GameFragment for this
(normally people use a DialogFragment instead which handles basically everything you have in line 2 to 18)
g
Okay uhm, I can add the
context
as an argument but moving it to a separate class may very well be out of the scope of my abilities with 48 hours of Android/Kotlin experience.
m
learning by doing.. I think it will be fine.
just create a new kotlin class
GamePopup
or something
move the popup function into that new class
(not trying to make something nice right now, only getting it to work)
g
Screenshot from 2020-03-11 13-30-00.png
m
you could also just copy the function into your other fragment as well, but that will be really ugly
g
Wait how is this even working if it says
context
is a type-mismatch?
but that will be really ugly
This whole codebase is... shudder
m
it expects a non null variable and you are giving it a nullable variable
g
The dev used ID selectors to read values from text instead of data
m
replace
context
with
requireContext
(runtime you will get the same exception. but the IDE might be happier)
or
context!
g
`
Copy code
var context: MainActivity?
Replace
MainActivity?
with
context!
?
m
no, but where you use it
Activities are contexts so MainActivity can be casted to Context without any problem, but you have MainActivity? which can only be casted to Context? (notice the ?, aka nullable sign)
g
Ohhh
I didn't know Kotlin allowed types to be multiple things at once
m
you have inheritance, so you can always just extend a base object, or/and you can add interfaces to a class allowing the class to be typecasted to any ancestor or interface type.
g
Okay so select the entire
joinGamePopup
and refactor it to a new class?
m
Lets see if that is possible (depending on how many things it uses from the GameFragment) but yes, start with that
g
image.png
They really single-purposed this ;..;
m
no problem, just continue 🙂
g
Okay its extracted
Copy code
package com.plei.screens.games.fragment

import androidx.fragment.app.Fragment
import com.plei.models.JoinGameModel

open class GamesFragment1 : Fragment() {
    fun joinGamePopup(gameJoin: JoinGameModel, position: Int) {
m
you should not have it in a fragment, just a class called GamePopup
Copy code
class GamePopup {
    fun joinGamePopup(gameJoin: JoinGameModel, position: Int) {
g
Which of the "refactor" options is that?
(also where should I put the class file?)
m
oh, sorry, with refactor i just ment the act of refactoring, not any special IDE tricks.
g
Ohh kk
So just create a file called
GamePopup.kt
anywhere and paste that method in there
Put it in
screens/games/fragment
?
m
yep, the placement of the file is less important
g
kk
Done 👌
m
in your GameFragment you can now create a
Copy code
val gamePopup = GamePopup()
somewhere in the beginning (still not super solution, but easiest to explain 🙂 )
g
It's got a ton of un-resolved references
Because it calls other methods and imports from the fragment
m
GameFragment or GamePopup?
g
GamePopup
m
ok, yea, that is what i was afraid of. Imports are easy, the IDE will help you with that
lets see which methods it complains about
g
Copy code
Unresolved reference: paymentProcessPopup
Unresolved reference: Intent
Unresolved reference: startActivity
Unresolved reference: R
Unresolved reference: PaymentActivity
Unresolved reference: isPaymentAdded
Unresolved reference: joinGame
Unresolved reference: positiveButton
Unresolved reference: getButton
Unresolved reference: sharedPreference
Unresolved reference: AlertDialog
Unresolved reference: setBackgroundDrawable
Unresolved reference: Dialog
Unresolved reference: WindowManager
c
Just pay a senior Android dev to look at it ?
g
@Christophe Smet Lol no chance the business owners would pay money for that, but I eventually got it after 14 hours 👍
c
haha too bad, welcome to Kotlin and Android tho 😉