如何拨打 API 电话。我是初学者

How to make API calls. I am a beginner

我想制作一个显示 funfact/joke 的应用程序,并且有一个按钮可以刷新 activity 以加载另一个 funfact/joke。

我制作了数据class、改造对象和界面并制作了布局,还在主体activity中编写了一些代码。应用程序运行,但 funfact/joke 未加载到 activity.

请帮忙,我是初学者

代码如下:

数据Class:

data class FunFact(
    val joke: String
)

改造对象:

object RetrofitInstance {

    val api: FunFactInterface by lazy {
        Retrofit.Builder()
            .baseUrl("https://geek-jokes.sameerkumar.website")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(FunFactInterface::class.java)
    }
}

接口:

interface FunFactInterface {

    @GET("/api?format=json")
    suspend fun getFacts(): Response<FunFact>
}

主要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布局:

<?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>

XML设计是这样的: APP Design

Edit/Update:感谢你们,应用程序正在获得响应。我从函数中删除了关键字 suspend 并添加了代码来处理 onFailure 场景。还按照建议在 mainActivity 中绑定之前删除了“val”。

更新代码:

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

        }



    }
}

应用程序运行并加载笑话,笑话的格式与期望的略有不同。非常感谢任何形式的帮助。

这是我得到的回复图片,我想删除“funfact”和“joke=”:

如果我没记错的话,您已正确设置所有内容,但没有在 loadData 方法中启动 API 调用。您可以通过在 enqueue 中编写 dataApi.getFacts().enqueue() 来做到这一点,您必须添加回调对象作为参数。也许这篇 link 对您更有帮助 https://futurestud.io/tutorials/retrofit-synchronous-and-asynchronous-requests

而不是这个

private suspend fun loadData() {

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

    }
}

应该是这样的

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

如果 MainActivity 中的代码是正确的,那么您没有设置实例变量 binding 的值,因为您正在 binding 中创建另一个具有相同名称的局部变量=13=]s onCreate

这里有一些你可以做的事情

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
    }
}