Home > Enterprise >  How to make API calls. I am a beginner
How to make API calls. I am a beginner

Time:01-24

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

CodePudding user response:

If I am not making a mistake you set everything up correctly however did not initiate the API call in your loadData method. You can do that by writing dataApi.getFacts().enqueue() inside enqueue you have to add Callback object as parameter. Maybe this link could be more helpful for you https://futurestud.io/tutorials/retrofit-synchronous-and-asynchronous-requests

Instead of this

private suspend fun loadData() {

    val dataApi = RetrofitInstance.api
    val results = dataApi.getFacts()
    if(results!=null){
        if (binding != null) {
            binding!!.textView.text= results.toString()
        }

    }
}

Should be like this

private suspend fun loadData() {

        val dataApi = RetrofitInstance.api
        val results = dataApi.getFacts().enqueue(object: Callback<FunFacts>{
            override fun onResponse(
                    call: Call<FunFacts>,
            response: Response<FunFacts>
                        ){
                // you can work with the response here
                if(results!=null){
                    if (binding != null) {
                        binding!!.textView.text= results.toString()
                    }

                }
            } override fun onFailure(call: Call<FunFacts>, t: Throwable) {
                // put code here when the call fails 
            }
        })
        
    }

CodePudding user response:

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 Activitys 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() {

        val dataApi = RetrofitInstance.api
        val results = dataApi.getFacts()
        if(results!=null){
            // no need for null check
            binding.textView.text= results.toString()
        }
    }
}
  •  Tags:  
  • Related