【发布时间】:2020-03-23 14:08:35
【问题描述】:
我正在为课程项目开发android app。我的应用程序有后端 (REST API),我在 Heroku 上开发和部署了它。现在我正在尝试从后端获取数据。我使用了Retrofit(network 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_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.EventListFragment">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:listData="@{viewModel.eventResponses}"
android:id="@+id/eventsRecyclerView"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
============================
events_list_layout.xml // ViewHolder 的布局
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="10dp"
app:cardCornerRadius="2dp"
app:cardPreventCornerOverlap="false">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
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_width="match_parent"
android:layout_height="wrap_content"
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_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/event_title"
android:text="@{eventsData.title}"
android:textColor="#000"
android:textSize="19sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
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 没有错误,因为应用程序运行但空白片段。我已经编辑了这篇文章并添加了我到目前为止编写的代码。请检查一下好吗?
标签: android json rest heroku kotlin