如何在 Kotlin 中发出 API 请求?

Posted

技术标签:

【中文标题】如何在 Kotlin 中发出 API 请求?【英文标题】:How to make an API request in Kotlin? 【发布时间】:2017-12-26 10:14:01 【问题描述】:

总的来说,我对 Kotlin 和 API 非常陌生,找不到使用这种语言创建 API 请求的语法。我正在创建网站的移动版本,因此我正在使用 android Studio 为已经建立的后端创建新的 UI。创建请求的步骤和语法是什么?任何帮助都深表感谢。

【问题讨论】:

查看这篇文章:codeflex.co/simple-restful-service-with-kotlin-and-spring-boot 【参考方案1】:

拥有set your Android Studio to use Kotlin 后,进行 REST 调用非常简单,并且与 Java 的逻辑几乎相同。


这是一个使用OkHttp 的 REST 调用示例:

build.gradle

dependencies 
    //...
    implementation 'com.squareup.okhttp3:okhttp:3.8.1'

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

MainActivity.kt

class MainActivity : AppCompatActivity() 

    private val client = OkHttpClient()

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        run("https://api.github.com/users/Evin1-/repos")
    

    fun run(url: String) 
        val request = Request.Builder()
                .url(url)
                .build()

        client.newCall(request).enqueue(object : Callback 
            override fun onFailure(call: Call, e: IOException) 
            override fun onResponse(call: Call, response: Response) = println(response.body()?.string())
        )
    


以下是其他库的一些更复杂的示例:

Network request in Kotlin with Retrofit Network request in Kotlin with Retrofit and coroutines Network request in Kotlin with Dagger, RxJava, Retrofit in MVP

【讨论】:

非常感谢您的详细回复。这肯定会帮助我取得一些进步。 任何从 onResponse 更新 UI 的尝试都会导致异常。最好改用 Retrofit。【参考方案2】:

我已经使用改造 2 创建了一个示例 API 调用。首先,将这些库添加到 gradle 中

implementation "com.squareup.retrofit2:retrofit:2.3.0"
implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
implementation "com.squareup.retrofit2:converter-gson:2.3.0"
implementation "io.reactivex.rxjava2:rxandroid:2.0.1"

然后创建一个类来配置 Retrofit 2,比如 Connect.kt

class Connect 

    companion object 

        private fun getRetrofit(Url:String):Retrofit 
            return Retrofit.Builder()
                    .addCallAdapterFactory(
                            RxJava2CallAdapterFactory.create())
                    .addConverterFactory(
                            GsonConverterFactory.create())
                    .baseUrl(Url)
                    .build()
        

        fun getApiData():Retrofit
            val retrofitApi = getRetrofit(Url.BASE_URL)
            return retrofitApi
        

        fun callApi():CallApi
            val retrofitCall = getApiData()
            return retrofitCall.create(CallApi::class.java)
        

    

我在 Url 类中创建了 Url,比如 Url.kt

class Url 
    companion object 
        const val BASE_URL = "your base url"
        const val URL = "your url"
    

为 API 调用创建接口

    interface CallApi 

        @GET(Url.URL)
//query needed if there is any query
        fun getApi(@Query("limit") limit: Int):
//model class is needed                
Observable<Model.Result>
    

根据你的响应创建一个模型类,示例响应是


    "data": 
        "children": [
            
                "data": 
                    "author": "",
                     "thumbnail":"",
                      "title":""
                     
                 ]
          
 

为了创建它的模型类,创建一个对象,比如模型

object Model 
    data class Result(val data: Data)
    data class Data(val children: List<Children>)
    data class Children(val data: Datas)
    data class Datas(val author: String,val thumbnail: String,val title: String)

然后创建一个样板类来从可以从任何活动调用的 api 中执行数据获取

class ApiData 
    companion object 
        const val count = 10
        val api by lazy  Connect.callApi() 
        var disposable: Disposable? = null
        fun apiData(callback:Response)
            disposable = api.getApi(count)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe (
                        result ->
                        callback.data(result,true)
                    ,  error ->
                        error.printStackTrace()
                    )

        

    
    interface Response 
        fun data(data:Model.Result,status:Boolean)
    

现在可以从像这样的活动中调用它,

ApiData.apiData( object :ApiData.Response
    override fun data(data: Model.Result, status: Boolean) 
        if(status)
            val items:List<Model.Children> = data.data.children
        
    

)

【讨论】:

【参考方案3】:

您可以使用RetrofitAsyncTask,例如AsyncTask

class getData() : AsyncTask<Void, Void, String>() 
    override fun doInBackground(vararg params: Void?): String? 
    

    override fun onPreExecute() 
        super.onPreExecute()
    

    override fun onPostExecute(result: String?) 
        super.onPostExecute(result)
    

对于Retrofit,请检查这个可怕的tutorial

【讨论】:

快速说明,从 Android R 开始,AsyncTask 已被弃用。developer.android.com/reference/android/os/AsyncTask【参考方案4】:

首先在AndroidManifest.xml中添加权限

  <uses-permission android:name="android.permission.INTERNET" />

二、安装谷歌依赖,Volley包

obs:volley 是用于进行 JSON 调用的官方 Google 软件包

链接:https://github.com/google/volley

访问项目结构

点击依赖

在所有依赖项中单击 +

点击库依赖

找到凌空并点击搜索

点击确定后点击应用,完成。

创建一个名为 RequestJSON 的新类,在我的例子中我使用的是 Kotlin

  import android.app.Activity
  import com.android.volley.*;
  import com.android.volley.toolbox.JsonObjectRequest
  import com.android.volley.toolbox.Volley
  import org.json.JSONObject
  import java.lang.Exception

  class RequestJSON 
      private val baseURL: String = "[PROTOCOL]://[HOST]:[PORT]/";
      private var url: String = "";
      private var method: String = "GET";
      private var requestData: JSONObject = JSONObject();
      private var queryString: String = "";

      companion object Factory 
          fun instance(): RequestJSON = RequestJSON();
      

      fun setURL(url: String): RequestJSON 
          this.url = url;
          return this;
      

      fun setMethod(method: String): RequestJSON 
          this.method = method.toLowerCase();
          return this;
      

      fun setData(data: JSONObject): RequestJSON 
          this.requestData = data;
          return this;
      

      private fun appendQuery(array: Array<String>, element: String): Array<String> 
          val list: MutableList<String> = array.toMutableList();
          list.add(element);

          return list.toTypedArray();
      

      fun setQuery(query: JSONObject) : RequestJSON 
          // limpa o queryString
          this.queryString = "";

          // obtendo as chaves do json
          val keys = query.keys();
          // criando array para conter as querys
          var querys: Array<String> = arrayOf();

          // obtendo os valores atravéz da chave e adicionando no array
          for(key in keys) 
              querys = this.appendQuery(querys, key + "=" + query.get(key));
          

          // verifica se existe valores no array
          // para conversão em stringQuery
          if (querys.size > 0) 
              this.queryString += "?";
              val size = querys.size;
              var count = 0;

              while (count < size) 
                  var querystring = "";

                  if (count == 0) 
                      querystring = querys[count];
                   else 
                      querystring = "&" + querys[count];
                  

                  this.queryString += querystring;
                  count++;
              
          

          return this;
      

      private fun getMethod(): Int 
          return when(this.method) 
              "get" -> 
                  Request.Method.GET;
              
              "post" -> 
                  Request.Method.POST;
              
              "put" -> 
                  Request.Method.PUT;
              
              "delete" -> 
                  Request.Method.DELETE;
              
              else -> Request.Method.GET;
          
      

      fun send(context: Activity, responseListiner: (response: JSONObject) -> Unit, errorListiner: (error: Exception) -> Unit) 
          val queue = Volley.newRequestQueue(context);
          var url = this.baseURL + this.url + this.queryString;
          var data: JSONObject = this.requestData;

          // limpando queryString após ser utilizado
          this.queryString = "";
          // limpando url após ser utilizado
          this.url = "";
          // limpando requestData após ser utilizado
          this.requestData = JSONObject();

          val jsonObjectRequest = JsonObjectRequest(this.getMethod(), url, data, fun (response) 
              responseListiner(response);
          , fun (error) 
              errorListiner(error);
          )

          // adicionando requesição ao queue
          queue.add(jsonObjectRequest);
      
  

测试使用

fun responseApiSuccess(response: JSONObject) 
    Log.i("request-success", response.toString());


fun responseApiError(error: Exception) 
    Log.e("request-error", error.toString());


fun callAPI() 
    var queryObject: JSONObject = JSONObject();

    queryObject.put("teste", "valor01");

    try 
        RequestJSON.instance().setURL("/").setMethod("GET").setQuery(queryObject).send(this, this::responseApiSuccess, this::responseApiError);
     catch (error: Exception) 
        error.printStackTrace();
    

【讨论】:

【参考方案5】:

Retrofit 是在 Android 上使用 API 的好工具。 Here 是我找到的关于如何在 Kotlin 上使用 Retrofit 的教程

【讨论】:

以上是关于如何在 Kotlin 中发出 API 请求?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 中自动发出 API 请求?

如何在 Django 中发出 json rpc 请求?

如何在一个 Visual Studio 解决方案中的 2 个内部 API 之间发出 API 请求?

如何在 React Native 中向 API 发出 POST 请求?

如何在不公开 API 密钥的情况下发出 POST 请求?

使用过期令牌发出同时 API 请求时如何避免多个令牌刷新请求