我正在为Scores App开发Grid RecyclerView。分数将通过API调用每5秒更新一次...
我正在将此library用于我的Recyclerview适配器。
我正在使用Observable Fields & List
。
我需要更新only the scores (textviews)
,但是现在RecyclerView每5秒更新一次。
请指引我正确的方向。谢谢!
class DashboardFragment : Fragment() {
private lateinit var dashboardViewModel: DashboardViewModel
private lateinit var binding: FragmentDashboardBinding
lateinit var retrofit: Retrofit
lateinit var apiService: APIService
lateinit var disposable: Disposable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
dashboardViewModel = ViewModelProvider(this).get(DashboardViewModel::class.java)
fetchData()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil
.inflate(inflater, R.layout.fragment_dashboard, container, false)
binding.viewModel = dashboardViewModel
return binding.root
}
fun fetchData() {
val interceptor = HttpLoggingInterceptor()
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
val gson = GsonBuilder()
.setLenient()
.create()
retrofit = Retrofit.Builder()
.baseUrl(APIService.BASE_URL)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
apiService = this.retrofit.create(APIService::class.java)
callIndicesEndpoint(null)
disposable = Observable.interval(1000, 2000, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ aLong: Long? -> this.refreshIndices(aLong)})
{ throwable: Throwable -> this.onError(throwable) }
}
@SuppressLint("CheckResult")
private fun callIndicesEndpoint(aLong: Long?) {
val observable =
apiService.indices
observable.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
.map { result: ObservableArrayList<Indices> -> result }
.subscribe(
{ data: ObservableArrayList<Indices> ->
this.handleResults(data)
}
) { t: Throwable ->
this.handleError(t)
}
}
@SuppressLint("CheckResult")
private fun refreshIndices(aLong: Long?) {
val observable =
apiService.indices
observable.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
.map { result: ObservableArrayList<Indices> -> result }
.subscribe({ data: ObservableArrayList<Indices> -> this.refreshResults(data)})
{ t: Throwable ->this.handleError(t)}
}
private fun handleResults(data: ObservableArrayList<Indices>) {
dashboardViewModel.populate(data)
}
private fun refreshResults(data: ObservableArrayList<Indices>) {
dashboardViewModel.refresh(data)
}
private fun onError(throwable: Throwable) {
Log.e(">>>", "ERROR")
}
private fun handleError(t: Throwable) {
Log.e("> >", t.localizedMessage + " - Err - " + t.cause)
//Add your error here.
}
override fun onPause() {
super.onPause()
disposable.dispose()
}
}
VIEWMODEL
class DashboardViewModel : ViewModel() {
val indices: ObservableList<Indices> = ObservableArrayList<Indices>()
fun populate(data: ArrayList<Indices>) {
indices.clear()
indices.addAll(data)
}
fun refresh(data: ArrayList<Indices>) {
// How to refresh only Items without recreating the List
}
val itemIds: ItemIds<Any> =
ItemIds { position, item -> position.toLong() }
val indicesItem: ItemBinding<Indices> =
ItemBinding.of<Indices>(BR.item, R.layout.item_futures)
}
答案 0 :(得分:0)
您可以使用广播接收器功能从recyclerview更新特定项目。
答案 1 :(得分:0)
我认为您需要使用DiffUtil
,它将对
DiffUtil找出已更改的内容,RecyclerView可以使用该信息仅更新已更改,添加,删除或移动的项目,这比重做整个列表要有效得多。
这是您可以用来获得帮助的课程:https://codelabs.developers.google.com/codelabs/kotlin-android-training-diffutil-databinding/#3
答案 2 :(得分:0)
当我有类似的东西时,我使用了DiffUtil。
我必须每X秒更新一次费率,而不能更改整个列表。
所以适配器应该是这样的:
class RatesAdapter :
ListAdapter<Rate, RecyclerView.ViewHolder>(RateDiffCallback()) {
private val baseRateView = 0
private val rateView = 1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == rateView) {
RateHolder(
RateItemBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)
} else {
BaseRateHolder(
BaseRateLayoutBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) {
baseRateView
} else rateView
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val rate = getItem(position)
if (holder.itemViewType == rateView) {
(holder as RateHolder).bind(rate)
holder.itemView.setOnClickListener {
swapper.itemSwap(rate)
}
} else {
(holder as BaseRateHolder).bind(rate)
}
}
class RateHolder(
private val binding: RateItemBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Rate) {
binding.apply {
rate = item
executePendingBindings()
}
}
}
class BaseRateHolder(
private val binding: BaseRateLayoutBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: Rate) {
binding.apply {
rate = item
executePendingBindings()
}
}
val value = binding.value
}
}
private class RateDiffCallback : DiffUtil.ItemCallback<Rate>() {
override fun areItemsTheSame(oldItem: Rate, newItem: Rate): Boolean {
return oldItem.currencyCode == newItem.currencyCode
}
override fun areContentsTheSame(oldItem: Rate, newItem: Rate): Boolean {
return oldItem.rate == newItem.rate
}
}
在这里我在适配器中使用了绑定,如果您不熟悉它,我也非常乐于解释
在活动中: 在onCreate之前:
private val ratesAdapter = RatesAdapter()
在onCreate中:
ratesList.adapter = ratesAdapter
每当您需要更新适配器(包括第一次调用适配器)时:
ratesAdapter.submitList(rates)
费率是我正在使用的模型类
rates 是
答案 3 :(得分:0)