I want to make an app that shows a funfact/joke and there's a button that refreshes the activity to load another funfact/joke.
I have made the data class, retrofit object and the interface and made the layout and also have written some code in the main activity. The app runs, however the funfact/joke isn't loaded on the activity.
Please help, I am a beginner.
Here are the codes:
Data Class:
data class FunFact(
val joke: String
)
Retrofit Object:
object RetrofitInstance {
val api: FunFactInterface by lazy {
Retrofit.Builder()
.baseUrl("https://geek-jokes.sameerkumar.website")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(FunFactInterface::class.java)
}
}
Interface:
interface FunFactInterface {
@GET("/api?format=json")
suspend fun getFacts(): Response<FunFact>
}
Main Activity:
class MainActivity : AppCompatActivity() {
var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
GlobalScope.launch {
loadData()
}
}
private suspend fun loadData() {
val dataApi = RetrofitInstance.api
val results = dataApi.getFacts()
if(results!=null){
if (binding != null) {
binding!!.textView.text= results.toString()
}
}
}
}
XML Layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="the fact"
android:textSize="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Another Fact"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
The XML Design is this: APP Design
Edit/Update: Thanks to you guys the app is getting response. I removed the keyword suspend from the functions and also added code to handle onFailure scenario. Also removed "val" before binding in mainActivity as suggested.
Updated Code:
class MainActivity : AppCompatActivity() {
var binding: ActivityMainBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding!!.root)
loadData()
binding!!.button.setOnClickListener{
loadData()
}
}
private fun loadData() {
val dataApi = RetrofitInstance.api
var results = dataApi.getFacts()
if (results!=null){
results.enqueue(object: Callback<FunFact>{
override fun onResponse(call: Call<FunFact>, response: Response<FunFact>) {
if(response!=null){
binding!!.textView.text= response.body().toString()
}
}
override fun onFailure(call: Call<FunFact>, t: Throwable) {
Toast.makeText(this@MainActivity,"Failure of response from API", Toast.LENGTH_SHORT)
.show()
}
})
}
}
}
The app runs and the joke is loaded, the format of the joke is little different than desired. Any kind of help is truly appreciated.
This is the image of the response that I got, I want to remove "funfact" and "joke=" :
If the code in MainActivity
is correct, then you're not setting the value of the instance variable binding
'cause you're creating another local variable with the same name in the Activity
s onCreate
Here's something you can do
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// set the value of the instance variable
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
GlobalScope.launch {
loadData()
}
}
private suspend fun loadData() = withContext(Dispatchers.Main) {
val dataApi = RetrofitInstance.api
val results = dataApi.getFacts()
binding.textView.text = results.body()?.joke
}
}