RecyclerView, loading data from Web-API: 如何防止RecyclerView初始为空?
RecyclerView, loading data from Web-API: How to prevent that the RecyclerView is initially empty?
我做了一个RecyclerView。初始数据是从 web-API 使用 Retrofit 加载的。因为缺少,是从服务器加载数据造成的,初始视图是空的。
目前我有一个 Thread.sleep() 用于延迟对 Recycler-View 适配器的数据分配。然后它按预期工作。请在代码中查看我的评论。
我怎样才能摆脱睡眠这个肮脏的把戏?这是如何正确完成的?
主要活动:
class MainActivity : AppCompatActivity() {
val TAG = MainActivity::class.java.simpleName
lateinit var recyclerView: RecyclerView
lateinit var addContactFab: FloatingActionButton
lateinit var viewModel: ContactsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
addContactFab = findViewById(R.id.addContactFab)
recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
viewModel = ViewModelProvider(this).get(ContactsViewModel::class.java)
// -- How can I get rid of this? ---
Thread.sleep(1000)
// ---------------------------------
recyclerView.adapter = ContactAdapter(viewModel.contactsList)
addContactFab.setOnClickListener {
val contact = Contact(id = System.currentTimeMillis(),
name = "Test Name", email = "Test Email", phone = "${System.currentTimeMillis()}")
viewModel.contactsList.add(contact)
recyclerView.adapter = ContactAdapter(viewModel.contactsList)
}
}
}
ViewModel-class:
class ContactsViewModel: ViewModel() {
val TAG = this::class.java.simpleName
var contactsList = ArrayList<Contact>()
init {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://jsonplaceholder.typicode.com")
.build()
val service = retrofit.create(ApiInterface::class.java)
val call = service.getContacts()
call.enqueue(object : Callback<List<Contact>> {
override fun onResponse(call: Call<List<Contact>>, response: Response<List<Contact>>) {
if (response.code() == 200) {
val contacts = response.body()
contacts?.forEach {
contactsList.add(Contact(
id = it.id,
name = it.name,
email = it.email,
phone = it.phone))
}
}
}
override fun onFailure(call: Call<List<Contact>>, t: Throwable) {
Log.d(TAG, "onFailure: ${t.localizedMessage}")
}
})
}
}
你无法摆脱来电的“等待时间”API。
事实上,让 UIThread 休眠或给它太多处理是一种非常糟糕的做法。
更糟糕的是,您的 API 可能需要 5 秒来加载数据,并且表现得好像没有数据一样。
更好的方法是在访问 activity 之前加载(因此您向用户显示一个进度条,告诉他在启动 activity 之前正在加载数据)
或者您可以在实际 activity 中显示一个进度条(例如,而不是 RecyclerView)。然后一旦你的数据被加载 (onSuccess),你可以 remove/hide 你的 progressBar 来设置适配器,或者调用 setData (这取决于你想要什么)
不要忘记处理 onFailure 场景的场景案例。
我做了一个RecyclerView。初始数据是从 web-API 使用 Retrofit 加载的。因为缺少,是从服务器加载数据造成的,初始视图是空的。
目前我有一个 Thread.sleep() 用于延迟对 Recycler-View 适配器的数据分配。然后它按预期工作。请在代码中查看我的评论。
我怎样才能摆脱睡眠这个肮脏的把戏?这是如何正确完成的?
主要活动:
class MainActivity : AppCompatActivity() {
val TAG = MainActivity::class.java.simpleName
lateinit var recyclerView: RecyclerView
lateinit var addContactFab: FloatingActionButton
lateinit var viewModel: ContactsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
addContactFab = findViewById(R.id.addContactFab)
recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
viewModel = ViewModelProvider(this).get(ContactsViewModel::class.java)
// -- How can I get rid of this? ---
Thread.sleep(1000)
// ---------------------------------
recyclerView.adapter = ContactAdapter(viewModel.contactsList)
addContactFab.setOnClickListener {
val contact = Contact(id = System.currentTimeMillis(),
name = "Test Name", email = "Test Email", phone = "${System.currentTimeMillis()}")
viewModel.contactsList.add(contact)
recyclerView.adapter = ContactAdapter(viewModel.contactsList)
}
}
}
ViewModel-class:
class ContactsViewModel: ViewModel() {
val TAG = this::class.java.simpleName
var contactsList = ArrayList<Contact>()
init {
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("https://jsonplaceholder.typicode.com")
.build()
val service = retrofit.create(ApiInterface::class.java)
val call = service.getContacts()
call.enqueue(object : Callback<List<Contact>> {
override fun onResponse(call: Call<List<Contact>>, response: Response<List<Contact>>) {
if (response.code() == 200) {
val contacts = response.body()
contacts?.forEach {
contactsList.add(Contact(
id = it.id,
name = it.name,
email = it.email,
phone = it.phone))
}
}
}
override fun onFailure(call: Call<List<Contact>>, t: Throwable) {
Log.d(TAG, "onFailure: ${t.localizedMessage}")
}
})
}
}
你无法摆脱来电的“等待时间”API。 事实上,让 UIThread 休眠或给它太多处理是一种非常糟糕的做法。 更糟糕的是,您的 API 可能需要 5 秒来加载数据,并且表现得好像没有数据一样。
更好的方法是在访问 activity 之前加载(因此您向用户显示一个进度条,告诉他在启动 activity 之前正在加载数据) 或者您可以在实际 activity 中显示一个进度条(例如,而不是 RecyclerView)。然后一旦你的数据被加载 (onSuccess),你可以 remove/hide 你的 progressBar 来设置适配器,或者调用 setData (这取决于你想要什么)
不要忘记处理 onFailure 场景的场景案例。