1

I have an android application I am working on in which I am making API request with Volley, after making the API call, I get a bunch of JSON objects returned. I now saved the values into a default values. after saving, I now tried displaying the values into my ui elements but everything is blank and does noy show the values. My codes are highlighted below

fun loginUser(context: Context, email: String, password: String, completion: (Boolean) -> Unit): Unit {

        val jsonBody = JSONObject()
        jsonBody.put("email", email)
        jsonBody.put("password", password)
        val requestBody = jsonBody.toString()

        val loginRequest = object : JsonObjectRequest(Method.POST, URL_LOGIN, null, Response.Listener {response ->

            try {
                userEmail = response.getString("user")
                authToken = response.getString("token")
                isLoggedIn = true
                completion(true)
            } catch (e: JSONException) {
                Log.d("JSON", "EXC:" + e.localizedMessage)
                completion(false)
            }
        }, Response.ErrorListener { error ->
            Log.d("ERROR", "Could not login user: $error")
            completion(false)

        }) {
            override fun getBodyContentType(): String {
                return "application/json; charset=utf-8"
            }
            override fun getBody(): ByteArray {
                return requestBody.toByteArray()
            }
        }
        Volley.newRequestQueue(context).add(loginRequest)
    }

fun findUserByEmail(context: Context, completion: (Boolean) -> Unit): Unit {
        val finUserByEmailRequest = object : JsonObjectRequest(Method.GET, "$URL_GET_USER$userEmail", null, Response.Listener {response ->
            try {
                UserDataService.name = response.getString("name")
                UserDataService.email = response.getString("email")
                UserDataService.avatarName = response.getString("avatarName")
                UserDataService.avatarColor = response.getString("avatarColor")
                UserDataService.id = response.getString("_id")
                val userDataChanaged = Intent(BROADCAST_USER_DATA_CHANGED)
                LocalBroadcastManager.getInstance(context).sendBroadcast(userDataChanaged)
                completion(true)
            } catch (e: JSONException) {
                Log.d("JSON", "EXC:" + e.localizedMessage)
                completion(false)
            }
        }, Response.ErrorListener { error ->
            Log.d("ERROR", "Could not find user: $error")
            completion(false)

        }) {
            override fun getBodyContentType(): String {
                return "application/json; charset=utf-8"
            }
            override fun getHeaders(): MutableMap<String, String> {
                val headers = HashMap<String, String>()
                headers["Authorization"] = "Bearer $authToken"
                return headers
            }
        }
        Volley.newRequestQueue(context).add(finUserByEmailRequest)
    }

my MainActivity

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)
        val toggle = ActionBarDrawerToggle(
                this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        drawer_layout.addDrawerListener(toggle)
        toggle.syncState()
   LocalBroadcastManager.getInstance(this).registerReceiver(userDataChangeReceiver, IntentFilter(BROADCAST_USER_DATA_CHANGED))
    }

    private val userDataChangeReceiver = object : BroadcastReceiver() {
        override fun onReceive(contect: Context?, intent: Intent?) {
            if (AuthService.isLoggedIn) {
                userNameNavHeader.text = UserDataService.name
                userEmailNavHeader.text = UserDataService.email

                val resourceId = resources.getIdentifier(UserDataService.avatarName, "drawable", packageName)
                userImageNavHeader.setImageResource(resourceId)
                userImageNavHeader.setBackgroundColor(UserDataService.returnAvatarColor(UserDataService.avatarColor))
                loginBtnNavHeader.text = "Logout"
            }
        }
    }

Where loginUser method gets called

fun loginLoginBtnClicked(view: View): Unit {

        val email = loginEmailTxt.text.toString()
        val password = loginPasswordTxt.text.toString()

        AuthService.loginUser(this, email, password) {success ->
            if (success) {
                AuthService.findUserByEmail(this) {fsuccess ->
                    if (fsuccess) {
                        finish()
                    }
                }
            }

        }
    }
King
  • 1,885
  • 3
  • 27
  • 84
  • How do you define `AuthService.isLoggedIn`? Is it true when you send your broadcast? It would be great to add some logging to the receiver to pinpoint the failure. Did the broadcast even arrive? – Eugen Pechanec Sep 25 '18 at 15:02
  • @EugenPechanec I have updated the question to include my Login Function – King Sep 25 '18 at 15:05
  • Broadcast Receivers are debuggable, did you try debugging, what's happening? – Khemraj Sharma Oct 03 '18 at 05:03
  • 1
    @King In your example, when/where do the loginUser and findUserByEmail methods get called? I don't see any methods calls to them from your example activity. Are they being called before your activity gets created/started? – maditya Oct 07 '18 at 03:45
  • @maditya I created another class to hold the Login function and that is where i called the LoginUser method – King Oct 08 '18 at 20:16
  • @maditya I updated the question to reflect this method implementation – King Oct 08 '18 at 20:18

1 Answers1

0

You first need to obtain the reference to the nav_header_main layout first to be able to update the text-View and image-view in the nav_header_main. Instead of using the id of the elements directly you should use nav_header reference then id like this

private val userDataChangeReceiver = object: BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {

        if(AuthService.isLoggedIn){
            Log.d("qwe", UserDataService.name)
            Log.d("qwe", UserDataService.email)
            Log.d("qwe", UserDataService.avatarName)
            Log.d("qwe", "Made it inside the broadcast bro")

            Log.d("qwe", "Wrap")


            nav_drawer_header_include.userEmailNavHeader.text = UserDataService.email
            nav_drawer_header_include.userNameNavHeader.text = UserDataService.name
            userEmailNavHeader.text = UserDataService.email
            val resourseid= resources.getIdentifier(UserDataService.avatarName,"drawable",packageName)
            nav_drawer_header_include.userImageNavHeader.setImageResource(resourseid)
            nav_drawer_header_include.loginBtnNavHeader.text="Logout"



        }

    }
}

We should use Log most often, it helped me to get to the problem directly instead of wasting my time on perfectly fine working things.

I too stumbled on this problem while doing the Android Kotlin course but after searching I found this is faced by many people they asked question on different platforms but no answer was provided. But after searching same terms "UI elements not updating android" found some stack overflow answers in java How to change text of a TextView in navigation drawer header?

They all explained to first get reference then we can be able to update the View. Then I tried and fortunately it worked perfectly fine.

PS: This is my first answer please don't mind the mistakes, I apologize.