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()
}
}
}
}
}
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.