我的 Recyclerview 有时需要刷新才能开始显示数据,有时需要很长时间才能显示数据,有时它就像一个魅力。我什至为 2 个回收站视图使用了相同的适配器,其中一个立即显示数据,但另一个根本没有显示,如下图所示:
当我添加另一个回收器视图但在使用相同适配器的不同片段中时,这个问题开始出现。我认为使用相同的适配器是问题,所以我创建了一个新的,但问题仍然存在。注意:我也使用相同的布局来显示回收站视图项目。任何想法都会非常有帮助。 谢谢
更新:代码
适配器:
import android.graphics.Paint
import android.view.LayoutInflater
import android.view.TextureView
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.ecommapp.R
import com.example.ecommapp.main_activity.data.Product
import kotlinx.android.synthetic.main.product_item_layout.view.*
class ProductItemAdapter(val listener: ProductItemAdapter.onItemClickListener) : ListAdapter<Product, ProductItemAdapter.ProductViewHolder>(Comparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val inflater = LayoutInflater.from(parent.context).inflate(R.layout.product_item_layout, parent, false)
return ProductViewHolder(inflater)
}
override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
val currentItem = getItem(position)
if (currentItem != null) {
holder.bind(currentItem)
}
}
inner class ProductViewHolder(view : View): RecyclerView.ViewHolder(view){
init {
view.setOnClickListener{
val position = adapterPosition
val product = getItem(position)
if(position != RecyclerView.NO_POSITION){
listener.onItemClick(product)
}
}
}
private val container = view.container_main
private val imageView = view.img_product_item_not_card
private val productName = view.tv_product_item_label
private val productNewPrice = view.tv_product_item_new_price
private val productOldPrice = view.tv_product_item_old_price
fun bind(product: Product) {
productName.text = product.title
productNewPrice.text = product.price
/*var temp = (product.price as Double ) * 1.5
var oldPrice = temp as String
productOldPrice.text = oldPrice
productOldPrice.paintFlags = productOldPrice.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG*/
//Context of the view
Glide.with(imageView.context) // Context
.load(product.image) // Data
.into(imageView) // View
}
}
interface onItemClickListener{
fun onItemClick(product : Product)
}
class Comparator : DiffUtil.ItemCallback<Product>() {
override fun areItemsTheSame(oldItem: Product, newItem: Product) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Product, newItem: Product) =
oldItem == newItem
}
}
查看模型:
import android.content.ContentValues.TAG
import android.util.Log
import androidx.lifecycle.*
import com.example.ecommapp.main_activity.data.Product
import com.example.ecommapp.main_activity.retrofit.ProductsApi
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.scopes.ViewModelScoped
import kotlinx.coroutines.launch
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
val api : ProductsApi
) : ViewModel() {
var new_collection_list : MutableLiveData<List<Product>>
var best_sellling_list : MutableLiveData<List<Product>>
init {
new_collection_list = MutableLiveData()
best_sellling_list = MutableLiveData()
get_best_selling_data()
get_new_collection_data()
}
fun get_new_collection_data(){
var call = api.get_products_desc()
call.enqueue(object : Callback<List<Product>> {
override fun onResponse(call: Call<List<Product>>, response: Response<List<Product>>) {
if (response.body() != null){
new_collection_list.postValue(response.body())
Log.d(TAG, "onResponse: Success Response")
}
else{
new_collection_list.postValue(null)
Log.d(TAG, "onResponse: Null Response")
}
}
override fun onFailure(call: Call<List<Product>>, t: Throwable) {
Log.d(TAG, "onFailure: Failure Response")
}
})
}
fun get_best_selling_data() {
var call = api.get_products_asc()
call.enqueue(object : Callback<List<Product>> {
override fun onResponse(call: Call<List<Product>>, response: Response<List<Product>>) {
if (response.body() != null){
best_sellling_list.postValue(response.body())
Log.d(TAG, "onResponse: Success Response")
}
else{
best_sellling_list.postValue(null)
Log.d(TAG, "onResponse: Null Response")
}
}
override fun onFailure(call: Call<List<Product>>, t: Throwable) {
Log.d(TAG, "onFailure: Failure Response")
}
})
}
fun on_swipe_refresh(){
get_new_collection_data()
get_best_selling_data()
}
}
片段:
package com.example.ecommapp.main_activity.fragments.home_fragment
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.example.ecommapp.R
import com.example.ecommapp.main_activity.data.Product
import com.example.ecommapp.main_activity.shared_files.recycler_view_adapters.ProductItemAdapter
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.android.synthetic.main.home_fragment_layout.*
@AndroidEntryPoint
class HomeFragment: Fragment(R.layout.home_fragment_layout), ProductItemAdapter.onItemClickListener {
lateinit var new_collection_list : LiveData<List<Product>>
lateinit var best_selling_list : LiveData<List<Product>>
val new_collections_adapter = ProductItemAdapter(this)
val best_selling_adapter = ProductItemAdapter(this)
val viewModel : HomeViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// New Collection Recycler View Setup
rv_new_collections.layoutManager = LinearLayoutManager(
activity?.applicationContext,
LinearLayoutManager.HORIZONTAL,
false
)
rv_new_collections.adapter = new_collections_adapter
// Best Selling Recycler View Setup
rv_best_selling.layoutManager = LinearLayoutManager(
activity?.applicationContext,
LinearLayoutManager.HORIZONTAL,
false
)
rv_best_selling.adapter = best_selling_adapter
//
set_data()
Handler().postDelayed({
if ( isConnected(activity?.applicationContext) ){
layout_new_collection_shimmer.visibility = View.INVISIBLE
rv_new_collections.visibility = View.VISIBLE
layout_best_selling_shimmer.visibility = View.INVISIBLE
rv_best_selling.visibility = View.VISIBLE
set_data()
}
else{
Toast.makeText(activity?.applicationContext, "No Internet Connection, Swipe to reload.", Toast.LENGTH_LONG )
.show()
}
}, 2000)
container_swipe.setOnRefreshListener(object : SwipeRefreshLayout.OnRefreshListener {
override fun onRefresh() {
if ( isConnected(activity?.applicationContext) ){
if( layout_new_collection_shimmer.visibility == View.INVISIBLE){
layout_new_collection_shimmer.visibility = View.INVISIBLE
rv_new_collections.visibility = View.VISIBLE
layout_best_selling_shimmer.visibility = View.INVISIBLE
rv_best_selling.visibility = View.VISIBLE
}
viewModel.on_swipe_refresh()
set_data()
}
else{
Toast.makeText(activity?.applicationContext, "No Internet Connection, Swipe to reload.", Toast.LENGTH_LONG )
.show()
}
// Must be added
container_swipe.isRefreshing = false
}
})
}
fun set_data(){
new_collection_list = viewModel.new_collection_list
best_selling_list = viewModel.best_sellling_list
new_collection_list.observe(viewLifecycleOwner, Observer {
new_collections_adapter.submitList(it)
new_collections_adapter.notifyDataSetChanged()
})
best_selling_list.observe(viewLifecycleOwner, Observer {
best_selling_adapter.submitList(it)
best_selling_adapter.notifyDataSetChanged()
})
}
fun isConnected(ctx: Context?): Boolean {
val hasInternet: Boolean
val connectivityManager =
ctx?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val networkCapabilities = connectivityManager.activeNetwork ?: return false
val actNw =
connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
hasInternet = when {
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
else -> false
}
} else {
hasInternet = try {
if (connectivityManager.activeNetworkInfo == null) {
false
} else {
connectivityManager.activeNetworkInfo?.isConnected!!
}
} catch (e: Exception) {
false
}
}
return hasInternet}
override fun onItemClick(product : Product) {
val action = HomeFragmentDirections.actionHomeFragmentToProductFragment(product, product.title, R.id.homeFragment)
findNavController().navigate(action)
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/container_swipe"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".main_activity.fragments.home_fragment.HomeFragment"
>
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.SearchView
android:id="@+id/search_view"
android:layout_width="0dp"
android:layout_height="50dp"
app:layout_constraintWidth_percent="0.9"
android:elevation="2dp"
android:outlineProvider="bounds"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="20dp"/>
<androidx.cardview.widget.CardView
android:id="@+id/img_advertisment"
android:layout_width="0dp"
android:layout_height="180dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/search_view"
app:layout_constraintWidth_percent="0.9"
android:background="#00000000"
app:cardElevation="0dp"
app:cardCornerRadius="10dp"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/advertisment"
/>
</androidx.cardview.widget.CardView>
<RelativeLayout
android:id="@+id/container_new_collection"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/img_advertisment"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintWidth_percent="0.9"
android:layout_marginTop="20dp"
>
<TextView
android:id="@+id/tv_new_collection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Collections"
android:textColor="@color/tomato"
android:textSize="25dp"
android:fontFamily="sans-serif-black"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show All"
android:textSize="20dp"
android:textColor="#c6c4ce"
android:fontFamily="sans-serif-black"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"/>
<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/layout_new_collection_shimmer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:shimmer_repeat_mode="restart"
app:shimmer_shape="linear"
android:layout_below="@id/tv_new_collection"
android:layout_marginTop="10dp">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
</LinearLayout>
</HorizontalScrollView>
</com.facebook.shimmer.ShimmerFrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="10dp"
android:id="@+id/rv_new_collections"
android:layout_width="wrap_content"
android:layout_height="350dp"
android:layout_below="@id/tv_new_collection"
tools:listitem="@layout/product_item_layout"
android:visibility="invisible"
/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/container_best_selling"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/container_new_collection"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintWidth_percent="0.9"
android:layout_marginTop="20dp"
>
<TextView
android:id="@+id/tv_best_selling"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Best Selling"
android:textColor="@color/tomato"
android:textSize="25dp"
android:fontFamily="sans-serif-black"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show All"
android:textSize="20dp"
android:textColor="#c6c4ce"
android:fontFamily="sans-serif-black"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"
/>
<com.facebook.shimmer.ShimmerFrameLayout
android:id="@+id/layout_best_selling_shimmer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:shimmer_repeat_mode="restart"
app:shimmer_shape="linear"
android:layout_marginTop="10dp"
android:layout_below="@id/tv_best_selling">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
<include layout="@layout/product_shimmer_layout"></include>
</LinearLayout>
</HorizontalScrollView>
</com.facebook.shimmer.ShimmerFrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_best_selling"
android:layout_width="wrap_content"
android:layout_height="350dp"
android:layout_below="@id/tv_best_selling"
tools:listitem="@layout/product_item_layout"
android:layout_marginTop="10dp"
android:visibility="invisible"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
答案 0 :(得分:0)
我想出了问题所在。 API 需要很多时间来发送数据。因此,回收器视图使用空值呈现视图。