Android REST API 调用,后端没有响应新记录

Posted

技术标签:

【中文标题】Android REST API 调用,后端没有响应新记录【英文标题】:Android REST API call with no response from back end for new records 【发布时间】:2020-03-23 14:08:35 【问题描述】:

我正在为课程项目开发android app。我的应用程序有后端 (REST API),我在 Heroku 上开发和部署了它。现在我正在尝试从后端获取数据。我使用了Retrofitnetwork API)和Moshi(用于解析JSON字符串)。

我第一次成功地从后端获得了3条记录的响应(这些记录是我在Ruby on Rails中写API时创建的)。然后为了测试应用程序,我从Postman 发送了POST 2 条记录,然后我再次运行应用程序。这一次我没有得到任何回应。然后我发送DELETE 操作最后 2 条添加的记录,我再次运行应用程序,这次我得到了旧记录的响应。然后我从Postman 发送另一个DELETE 操作以获取旧记录之一并发送POST 操作。然后应用程序没有显示任何响应。我删除了新记录,然后应用显示旧记录。

通常app 仅显示旧记录。每当我发送新的POST 操作时,我都没有得到回复。我对正在发生的事情感到惊讶。有人可以告诉我可能是什么问题吗?我已经清除了手机中的所有caches,重启手机,重新安装了应用程序,但问题仍然存在。

(我可以从邮递员和浏览器成功获取所有数据)

EventApiService.kt // 我定义 Retrofit 和 Moshi 对象的地方

private val BASE_URL = "https://eventnotifierjson2.herokuapp.com/"

private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .addCallAdapterFactory(CoroutineCallAdapterFactory())
    .baseUrl(BASE_URL)
    .build()


interface EventApiInterface
    @GET("events")
    fun getEvents():
            Deferred<List<Event>>


object EventApi 

    val retrofitService : EventApiInterface by lazy 
        retrofit.create(EventApiInterface::class.java)
    

=============================EventsListFragment 的视图模型

class EventListViewModel: ViewModel()

     private val _eventResponses = MutableLiveData<List<Event>>()

    val eventResponses : LiveData<List<Event>>
        get() = _eventResponses


    private val _responseStatus = MutableLiveData<String>()

    val responseStatus : LiveData<String>
        get() = _responseStatus

    private val eventCoroutineJob = Job()

    private val eventCoroutineScope = CoroutineScope(eventCoroutineJob  + Dispatchers.Main)

    init 
        retrieveEventsInBackground()
    
    private fun retrieveEventsInBackground() 
        eventCoroutineScope.launch 
            // Get the Deferred object for our Retrofit request
            var getPropertiesDeferred = EventApi.retrofitService.getEvents()
            try 
                // this will run on a thread managed by Retrofit
                val listResult = getPropertiesDeferred.await()
                _eventResponses.value = listResult
                Log.i("RETROFIT ZEK: ", _eventResponses.value.toString())
             catch (e: Exception) 
                _responseStatus.value = e.message
            
        
    


    override fun onCleared() 
        super.onCleared()
        eventCoroutineJob.cancel()
    


=================================

class EventListFragment : Fragment() 

    lateinit var binding : FragmentEventListBinding
    private val viewModel: EventListViewModel by lazy 
        ViewModelProviders.of(this).get(EventListViewModel::class.java)
    
    private lateinit var eventAdapter : EventsRecyclerAdapter

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? 


        binding = FragmentEventListBinding.inflate(inflater)
        binding.setLifecycleOwner(this)
        binding.viewModel = viewModel
        initializeRecyclerView()
        return binding.root
    

    private fun initializeRecyclerView()
        binding.eventsRecyclerView.apply 
             layoutManager = LinearLayoutManager(this@EventListFragment.context)
            val cardDecoration = CardViewDecoration(30)
            addItemDecoration(cardDecoration)
            eventAdapter = EventsRecyclerAdapter()
            adapter = eventAdapter
        
    

用于显示回收站视图和图像的 BindingAdapters

@BindingAdapter("listData")
fun bindRecyclerView(recyclerView: RecyclerView,  data: List<Event>?)
    val adapter = recyclerView.adapter as EventsRecyclerAdapter
    adapter.submitList(data)


@BindingAdapter("imageUrl")
fun bindImage(imgView: ImageView, imgUrl: String?) 
    imgUrl?.let 
        val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
        Glide.with(imgView.context)
            .load(imgUri)
            .apply(RequestOptions()
                .placeholder(R.drawable.ic_gerald_g_boy_face_cartoon)
                .error(R.drawable.ic_gerald_g_boy_face_cartoon))
            .into(imgView)
    

==========================从 JSON 数组中检索到的事件对象的数据类

data class Event(val id: Int,
                 val title: String,
                 val description: String,
                 val country: String,
                 val city:  String,
                 @Json(name = "event_location") val eventLocation : String,
                 @Json(name = "event_date") val eventDate : String,
                 @Json(name = "event_time") val eventTime: String,
                 @Json(name = "event_status") val eventStatus: String,
                 @Json(name = "user_id") val userId: Int,
                 @Json(name = "created_at") val createdAt: String,
                 @Json(name = "updated_at") val updatedAt: String,
                 val eventimage : EventImage)
data class EventImage(
   val url: String

)

fragment_event_list.xml // 我将 ViewHolder 膨胀到的视图

<?xml version="1.0" encoding="utf-8"?>
<layout 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">
   <data>
      <variable
          name="viewModel"
          type="com.mobapproject.eventsroom.modelviews.EventListViewModel" />
   </data>
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_
    android:layout_
    tools:context=".fragments.EventListFragment">

   <androidx.recyclerview.widget.RecyclerView
       android:layout_
       android:layout_
       app:listData="@viewModel.eventResponses"
       android:id="@+id/eventsRecyclerView"/>

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

============================events_list_layout.xml // ViewHolder 的布局

<androidx.cardview.widget.CardView

    android:layout_
    android:layout_

    app:cardElevation="10dp"
    app:cardCornerRadius="2dp"
    app:cardPreventCornerOverlap="false">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_
        android:layout_>

        <ImageView
            android:layout_
            android:layout_
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:imageUrl="@eventsData.eventimage.url"
            android:id="@+id/event_image"
            android:padding="0dp"
            android:layout_margin="0dp"
            android:adjustViewBounds="true"
            android:scaleType="centerCrop"
            />


        <LinearLayout
            android:layout_
            android:layout_
            app:layout_constraintTop_toBottomOf="@id/event_image"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:orientation="vertical"
            android:padding="10dp"
            android:id="@+id/container1">
            <TextView
                android:layout_
                android:layout_
                android:id="@+id/event_title"
                android:text="@eventsData.title"
                android:textColor="#000"
                android:textSize="19sp"/>

            <TextView
                android:layout_
                android:layout_
                android:id="@+id/event_location"
                android:text="@eventsData.eventLocation"
                android:textSize="15sp"
                android:layout_marginTop="10dp"/>


        </LinearLayout>



    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.cardview.widget.CardView>
</layout>

============================== JSON 响应如下所示


"id": 1,
"title": "Dummy title",
"description": "Dummy Description",
"country": "Italy",
"city": "Rome",
"event_location": "Rome",
"event_date": "2019-11-26",
"event_time": "2000-01-01T21:28:16.000Z",
"event_status": "open",
"user_id": 1,
"created_at": "2019-11-25T01:51:36.075Z",
"updated_at": "2019-11-25T01:51:36.075Z",
"eventimage": 
      "url": "http://res.cloudinary.com/zakstorage/....."
        

【问题讨论】:

向我们展示代码或错误日志,以便我们找出问题所在。 @Jayanth 没有错误,因为应用程序运行但空白片段。我已经编辑了这篇文章并添加了我到目前为止编写的代码。请检查一下好吗? 【参考方案1】:

我遇到了问题,我犯了一个错误。我一直在向 POST 操作发送不正确的参数,而 Moshi 无法解析 NULL 值

【讨论】:

以上是关于Android REST API 调用,后端没有响应新记录的主要内容,如果未能解决你的问题,请参考以下文章

Rest api有时返回字符串有时返回json对象

如何在android中执行并行REST API调用

Android 我应该使用 AsyncTask 还是 IntentService 进行 REST API 调用? [复制]

通过更改android中的参数来重复调用rest api的最佳方法是啥

REST API 对 Fragment 的响应 - Android Studio

Android REST API 连接