如何拨打 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
}
}
我想制作一个显示 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
}
}