【问题标题】:populate spinner with retrofit and moshi用改造和 moshi 填充微调器
【发布时间】:2018-05-20 09:57:18
【问题描述】:

我是 android 开发(java 或 kotlin)的初学者。我正在尝试使用改造和 moshi 从 json 填充微调器,但我不知道如何将它填充到微调器中。老实说,我不知道 Json 数据的返回是否正确,因为 Log.d() 返回的不是 dump() laravel 或 php 的详细信息。

活动onCreate中的脚本(请阅读脚本的注释,我将Log.d()的调试结果放在那里):

val task = object : AsyncTask<Void, Void, Response<List<ProductTypeResponse>>>() {
        override fun doInBackground(vararg params: Void): Response<List<ProductTypeResponse>> {

            val typeAPI = RestAPI()
            val callResponse = typeAPI.getNews()
            val response = callResponse.execute()

            return response

        }

        override fun onPostExecute(response: Response<List<ProductTypeResponse>>) {
            if (response.isSuccessful) {
                val news = response.body()
                Log.d("test:", news!![0].data.toString()) //  method 'java.lang.String com.example.mockie.tigaer.api.TypeDataResponse.toString()' on a null object reference
                Log.d("test:", news!!.size.toString()) // it says 67 but the data from the url is 63 array of json object
                Log.d("test:", news!![0].toString()) // com.example.mockie.tigaer.api.ProductTypeResponse@f17fd5e
            }
        }

RestApi.kt

import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

class RestAPI() {

private val tigaerApi: TigaerApi

init {
    val retrofit = Retrofit.Builder()
            .baseUrl("http://app.tigaer.id/laravel/")
            .addConverterFactory(MoshiConverterFactory.create())
            .build()

    tigaerApi = retrofit.create(TigaerApi::class.java)
}

fun getNews(): Call<List<ProductTypeResponse>> {
    return tigaerApi.getTop()
}
}

ApiModel.kt

package com.example.mockie.tigaer.api

class ProductTypeResponse(val data: TypeDataResponse)

class TypeDataResponse(
    val children: List<ProductTypeChildrenResponse>
 )

 class ProductTypeChildrenResponse(val data: ProductTypeDataResponse)

 class ProductTypeDataResponse(
    val productType: String,
    val readable: String
 )

TigaerApi.kt

import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface  TigaerApi {
@GET("api/type")
fun getTop(): Call<List<ProductTypeResponse>>
}

返回 Json:https://jsoneditoronline.org/?id=ce90c41b859218e746e41d64eddb4c30

所以我的问题是:

  1. 是否有任何函数可以像 laravel 中那样详细调试对象/数组?
  2. 如何将我的 json 返回数据填充到微调器中?

【问题讨论】:

    标签: android json kotlin retrofit2 moshi


    【解决方案1】:

    我在这篇文章中有一个想法,也许我的逻辑可以帮助这里的任何人

    这是我的 JSON

    {
    "success": 1,
    "dataset": [
        {
            "id": "3",
            "nama": "Rush"
        },
        {
            "id": "5",
            "nama": "Avanza"
        },
        {
            "id": "6",
            "nama": "Innova"
        },
        {
            "id": "14",
            "nama": "Sienta"
        },
        {
            "id": "15",
            "nama": "Alphard"
        },
        {
            "id": "16",
            "nama": "Calya"
        }
    ],
    "sql_duration": 0.0013179779052734375,
    "auth_duration": 1.9073486328125e-6,
    "req_duration": 0.004480123519897461,
    "debug_duration": []
    }
    

    这是我的 API 服务

    ApiMain.kt

    class ApiMain : Application(){
    private var BASE_URL = "your url in here"
    
    private val client = OkHttpClient().newBuilder()
        .addInterceptor(HttpLoggingInterceptor().apply {
            level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
        })
        .readTimeout(30, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .build()
    private val retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
    val services: ApiServices = retrofit.create(ApiServices::class.java)
    }
    

    这是我的 API 服务

    ApiServices.kt

    interface ApiServices {
        @GET("yourlink")
        fun MerkKendaraan():Call<MerkKendaraan>
    }
    

    这是我的模型

    kendaraan.kt

    data class MerkKendaraan(
    @SerializedName("success")
    @Expose
    var success: Int? = null,
    
    @SerializedName("dataset")
    @Expose
    var dataset: List<MerkMobil>? = null,
    
    @SerializedName("sql_duration")
    @Expose
    var sql_duration: String? = null,
    
    @SerializedName("auth_duration")
    @Expose
    var auth_duration: String? = null,
    
    @SerializedName("req_duration")
    @Expose
    var req_duration: String? = null
    
    )
    
    data class MerkMobil(
        @SerializedName("id")
        @Expose
        var id: String? = null,
    
        @SerializedName("nama")
        @Expose
        var nama: String? = null
    )
    

    这是我的主要活动

    添加肯达兰

    class AddKendaraan : AppCompatActivity() {
    
    private var merk : ArrayList<MerkMobil> = ArrayList()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_kendaraan)
        configspinnermobil()
    }
    
    private fun configspinnermobil() {
        val spinner: Spinner = findViewById(R.id.spinnerMerk)
    
        ApiMain().services.MerkKendaraan().enqueue(object :
            Callback<MerkKendaraan> {
            override fun onResponse(call: Call<MerkKendaraan>, response: Response<MerkKendaraan>) {
                //Tulis code jika response sukses
                Log.d("data api", "data masuk")
                if(response.code() == 200){
                        merk = response.body()?.dataset as ArrayList<MerkMobil>
                    var data : MutableList<String> = ArrayList()
                    merk.forEach {
                        data.add(0,it.nama.toString())
                    }
                    spinner.adapter = ArrayAdapter<String>(this@AddKendaraan, R.layout.support_simple_spinner_dropdown_item, data)
                }else{
    
                }
    
            }
            override fun onFailure(call: Call<MerkKendaraan>, t: Throwable){
                //Tulis code jika response fail
                Toast.makeText(applicationContext, t.message, Toast.LENGTH_LONG).show()
                Log.d("data api", "data tidak masuk")
    
            }
        })
    }
    

    【讨论】:

      【解决方案2】:

      这是相同的代码,我只修改并集成到您的代码中:

      “MainActivity.kt”类:

       class MainActivity : AppCompatActivity() {
      
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)
      
          var spinner: Spinner = findViewById(R.id.spinner)
      
          val task = object : AsyncTask<Void, Void, Response<List<ProductTypeDataResponse>>>() {
              override fun doInBackground(vararg params: Void): Response<List<ProductTypeDataResponse>> {
      
                  val typeAPI = RestAPI()
                  val callResponse = typeAPI.getNews()
                  val response = callResponse.execute()
      
                  return response
      
              }
      
              override fun onPostExecute(response: Response<List<ProductTypeDataResponse>>) {
                  if (response.isSuccessful) {
                      val news: List<ProductTypeDataResponse>? = response.body()
      
                      var adapter: SpinnerAdapter = SpinnerAdapter(this@MainActivity, news!!);
      
                      spinner.adapter=adapter
      
      
                     }
              }
          }.execute()
      }
      }
      

      现在布局“activity_main”:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout 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="com.example.ankitpatidar.checkkotlin.MainActivity">
      
      <Spinner
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:id="@+id/spinner"></Spinner>
      </LinearLayout>
      

      现在 Spinner 适配器为“SpinnerAdapter”:

       class SpinnerAdapter internal constructor(internal var context: Context, internal var list: List<ProductTypeDataResponse>) : BaseAdapter() {
      override fun getCount(): Int {
          return list.size
      }
      
      override fun getItem(i: Int): Any? {
          return null
      }
      
      override fun getItemId(i: Int): Long {
          return 0
      }
      
      override fun getView(i: Int, view: View?, viewGroup: ViewGroup): View {
          var view = view
          if (view == null) {
              val inflater = LayoutInflater.from(context)
      
              view = inflater.inflate(R.layout.item, viewGroup, false)
          }
      
          val textView = view!!.findViewById<TextView>(R.id.textView)
      
          textView.text = list[i].productType + " " + list[i].readable
      
          return textView
      
      }
      }
      

      微调器项目布局为“项目”:

       <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
      android:layout_height="match_parent">
      
      <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:id="@+id/textView"/>
      
      </LinearLayout>
      

      现在对现有文件进行一些更改:

      “ApiModel.kt”:

       class TypeDataResponse(
          val children: List<ProductTypeChildrenResponse>
       )
      
       class ProductTypeChildrenResponse(val data: ProductTypeDataResponse)
      
       class ProductTypeDataResponse(
          val productType: String,
          val readable: String
       )
      

      “RestAPI.kt”

       class RestAPI() {
      
      private val tigaerApi: TigaerApi
      
      init {
          val retrofit = Retrofit.Builder()
                  .baseUrl("http://app.tigaer.id/laravel/")
                  .addConverterFactory(MoshiConverterFactory.create())
                  .build()
      
          tigaerApi = retrofit.create(TigaerApi::class.java)
      }
      
      fun getNews(): Call<List<ProductTypeDataResponse>> {
          return tigaerApi.getTop()
      }
      }
      

      因此它会为你工作。

      【讨论】:

      • 你的回答给了我希望。非常感谢。我今天会试试,让你知道结果。谢谢!
      • @卡卡西。你好吗?不要担心它的工作原理。我最后检查并验证了。
      • 它就像一个魅力。谢谢!你让我开心!我将尝试了解您的每个代码的含义。
      • 非常感谢@kakashi 给我带来这么大的乐趣。你也让我在这个补充之后的一天。请随时问我。我的联系人:ankitpatidar030@gmail.com
      【解决方案3】:

      有没有像 laravel 一样详细调试对象/数组的函数?

      通过此操作以调试模式运行您的应用。 https://developer.android.com/studio/debug/index.html

      您始终可以在应用程序运行时使用断点来计算表达式。而不是记录在这一行放置一个断点。

       val news = response.body()
      

      因此,当您收到来自服务器的响应时,应用程序将在此时停止,您可以详细检查收到的响应内容。

      如何将我的 json 返回数据填充到微调器中?

      如果您从提供的链接中显示的 Json 格式的服务器获得响应,则必须将数据解析为对象列表 (POJO)。 然后您必须将此数据转发(也许您必须遍历列表以获取所需数据,因为每个对象中有两个字段)到适配器并将该适配器设置为您的微调器。在下面的链接中解释得很清楚。 https://developer.android.com/guide/topics/ui/controls/spinner.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多