Как можно реализовать загрузку recycler view?

Ссылка скопирована
1 ответ

Как можно реализовать загрузку recycler view?
В фрагменте HistoryFragment я инициализирую адаптер:

override fun onCreateView(         inflater: LayoutInflater, container: ViewGroup?,         savedInstanceState: Bundle?     ): View {         Log.d("MyLog", "onCreateView - History")         binding = FragmentHistoryBinding.inflate(inflater, container, false)         initRcView() //... }  private fun initRcView() = with(binding) {         rcViewHistory.layoutManager = LinearLayoutManager(activity)         adapter = RecyclerViewAdapter(this@HistoryFragment, requireContext())         rcViewHistory.adapter = adapter         //Cache elements of list         rcViewHistory.setItemViewCacheSize(120)     }

override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { Log.d("MyLog", "onCreateView - History") binding = FragmentHistoryBinding.inflate(inflater, container, false) initRcView() //... } private fun initRcView() = with(binding) { rcViewHistory.layoutManager = LinearLayoutManager(activity) adapter = RecyclerViewAdapter(this@HistoryFragment, requireContext()) rcViewHistory.adapter = adapter //Cache elements of list rcViewHistory.setItemViewCacheSize(120) }

После этого я вызываю observer, достающий данные из БД и передающие их в adapter:

private fun observer(month: String, currentMonth: String) {         mainViewModel.getMonthNotes(month).observe(viewLifecycleOwner) {             if (it == null && month == currentMonth) {                 Log.d("MyLog", "List is empty")                 binding.rcViewHistory.visibility = View.GONE                  binding.EmptyView.emptyView.visibility = View.VISIBLE                 val openAnim = AnimationUtils.loadAnimation(context, R.anim.enter_empty_view)                 binding.EmptyView.emptyView.startAnimation(openAnim)             } else {                 binding.rcViewHistory.visibility = View.VISIBLE                 binding.EmptyView.emptyView.visibility = View.GONE                 adapter.submitList(it)             }         }     }

private fun observer(month: String, currentMonth: String) { mainViewModel.getMonthNotes(month).observe(viewLifecycleOwner) { if (it == null && month == currentMonth) { Log.d("MyLog", "List is empty") binding.rcViewHistory.visibility = View.GONE binding.EmptyView.emptyView.visibility = View.VISIBLE val openAnim = AnimationUtils.loadAnimation(context, R.anim.enter_empty_view) binding.EmptyView.emptyView.startAnimation(openAnim) } else { binding.rcViewHistory.visibility = View.VISIBLE binding.EmptyView.emptyView.visibility = View.GONE adapter.submitList(it) } } }

И вот код самого адаптера:

class RecyclerViewAdapter(     private val listener: Listener, private val context: Context ) : ListAdapter<ItemsList, RecyclerViewAdapter.ItemHolder>(AsyncDifferConfig.Builder(ItemComparator()).build()) {      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {         return ItemHolder.create(parent)     }      override fun onBindViewHolder(holder: ItemHolder, position: Int) {         if (position != 0) {             val previousItem = getItem(position - 1)             holder.setData(getItem(position), listener, context, position, previousItem)         }          else {             holder.setData(getItem(position), listener, context, position, null)         }     }      fun onSwipedRc(position: Int) {         val item = getItem(position)         val id = item.id         Log.d("MyLog", "Deleted item id was $id")          listener.deleteItem(id!!, position)     }      class ItemHolder(view: View) : ViewHolder(view) {         private val binding = ListItemBinding.bind(view)         private var isAnim = false          fun setData(note: ItemsList, listener: Listener, context: Context,                     position: Int, previousItem: ItemsList?) = with(binding) {             val name = note.categoryName!!             val nameResID = R.string::class.java.getField(name).getInt(null)              tvCategoryTitle.setText(nameResID)             Glide.with(context).load(R.drawable::class.java.getField(formatIcPath(name)).getInt(null))                 .error(R.drawable.ic_others)                 .placeholder(R.drawable.ic_others).into(categoryIv)             tvPurchaseTitle.text = note.purchaseName             tvDescription.text = note.description             if (tvDescription.text.isNotEmpty()) {                 ivArrow.visibility = View.VISIBLE             }             tvAmount.text = formatTrim(String.format("%.2f", note.amount))              //Make date to string and set day of week             val date = note.displayed_date             if (date != null) {                 if (position == 0 || date != previousItem?.displayed_date) {                     tvDay.setText(getDayOfWeek(date))                     tvDate.text = date.substring(0, 2)                     binding.tvDate.visibility = View.VISIBLE                     binding.tvDay.visibility = View.VISIBLE                 } else {                     binding.tvDate.visibility = View.GONE                     binding.tvDay.visibility = View.GONE                 }             } else {                 Log.d("MyLog", "Date is null")                 binding.tvDate.visibility = View.GONE                 binding.tvDay.visibility = View.GONE             }              if (!note.description.isNullOrEmpty()) {                 itemView.setOnClickListener {                     Log.d("MyLog", "Clicked on item")                     if (isAnim) {                         return@setOnClickListener                     }                      if (BottomList.visibility == View.GONE && tvDescription.text.isNotEmpty()) {                         Log.d("MyLog", "VISIBLE description")                         val expItem = Item                         val expHeight = BottomList                          expandView(expItem, expHeight, context)                          val animRotation = RotateAnimation(                             0f, 180f,                             Animation.RELATIVE_TO_SELF, 0.5f,                             Animation.RELATIVE_TO_SELF, 0.5f                         )                         animRotation.duration = 500                         animRotation.fillAfter = true                          ivArrow.startAnimation(animRotation)                     } else if (BottomList.visibility == View.VISIBLE) {                         Log.d("MyLog", "GONE description")                          val collItem = Item                         val collHeight = BottomList                          collHeight.visibility = View.GONE                         collapseView(collItem, collHeight)                          val animRotation = RotateAnimation(                             180f, 0f,                             Animation.RELATIVE_TO_SELF, 0.5f,                             Animation.RELATIVE_TO_SELF, 0.5f                         )                         animRotation.duration = 250                         animRotation.fillAfter = true                          ivArrow.startAnimation(animRotation)                     }                 }             }              itemView.setOnLongClickListener {                 listener.onLongClickItem(note, itemView)                  true             }         }          private fun expandView(expItem: View, expHeight: View, context: Context) {             isAnim = true              val initHeight = expItem.height             expHeight.measure(                 View.MeasureSpec.makeMeasureSpec(expItem.width, View.MeasureSpec.EXACTLY),                 View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)             )             val targetHeight = initHeight + expHeight.measuredHeight              val animator = ValueAnimator.ofInt(initHeight, targetHeight)             animator.addUpdateListener { animation ->                 val value = animation.animatedValue as Int                 val layoutParams = expItem.layoutParams                 layoutParams.height = value                 expItem.layoutParams = layoutParams             }             animator.duration = 200              animator.start()              animator.addListener(object: AnimatorListenerAdapter() {                 override fun onAnimationEnd(animation: Animator) {                     super.onAnimationEnd(animation)                     isAnim = false                     val animFadeIn = AnimationUtils.loadAnimation(context, R.anim.fade_in)                     expHeight.startAnimation(animFadeIn)                     expHeight.visibility = View.VISIBLE                 }             })         }          private fun collapseView(collItem: View, collHeight: View) {             isAnim = true              val initHeight = collItem.height             collHeight.measure(                 View.MeasureSpec.makeMeasureSpec(collItem.width, View.MeasureSpec.EXACTLY),                 View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)             )             val targetHeight = initHeight - collHeight.measuredHeight              val animator = ValueAnimator.ofInt(initHeight, targetHeight)             animator.addUpdateListener { animation ->                 val value = animation.animatedValue as Int                 val layoutParams = collItem.layoutParams                 layoutParams.height = value                 collItem.layoutParams = layoutParams             }             animator.duration = 200             animator.start()             animator.addListener(object: AnimatorListenerAdapter() {                 override fun onAnimationEnd(animation: Animator) {                     super.onAnimationEnd(animation)                     isAnim = false                 }             })         }         //...             companion object {             fun create(parent: ViewGroup): ItemHolder {                 return ItemHolder(                     LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)                 )             }         }     }      class ItemComparator : DiffUtil.ItemCallback<ItemsList>() {         override fun areItemsTheSame(oldItem: ItemsList, newItem: ItemsList): Boolean {             return oldItem.id == newItem.id         }          override fun areContentsTheSame(oldItem: ItemsList, newItem: ItemsList): Boolean {             return oldItem == newItem         }     } }

class RecyclerViewAdapter( private val listener: Listener, private val context: Context ) : ListAdapter<ItemsList, RecyclerViewAdapter.ItemHolder>(AsyncDifferConfig.Builder(ItemComparator()).build()) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder { return ItemHolder.create(parent) } override fun onBindViewHolder(holder: ItemHolder, position: Int) { if (position != 0) { val previousItem = getItem(position - 1) holder.setData(getItem(position), listener, context, position, previousItem) } else { holder.setData(getItem(position), listener, context, position, null) } } fun onSwipedRc(position: Int) { val item = getItem(position) val id = item.id Log.d("MyLog", "Deleted item id was $id") listener.deleteItem(id!!, position) } class ItemHolder(view: View) : ViewHolder(view) { private val binding = ListItemBinding.bind(view) private var isAnim = false fun setData(note: ItemsList, listener: Listener, context: Context, position: Int, previousItem: ItemsList?) = with(binding) { val name = note.categoryName!! val nameResID = R.string::class.java.getField(name).getInt(null) tvCategoryTitle.setText(nameResID) Glide.with(context).load(R.drawable::class.java.getField(formatIcPath(name)).getInt(null)) .error(R.drawable.ic_others) .placeholder(R.drawable.ic_others).into(categoryIv) tvPurchaseTitle.text = note.purchaseName tvDescription.text = note.description if (tvDescription.text.isNotEmpty()) { ivArrow.visibility = View.VISIBLE } tvAmount.text = formatTrim(String.format("%.2f", note.amount)) //Make date to string and set day of week val date = note.displayed_date if (date != null) { if (position == 0 || date != previousItem?.displayed_date) { tvDay.setText(getDayOfWeek(date)) tvDate.text = date.substring(0, 2) binding.tvDate.visibility = View.VISIBLE binding.tvDay.visibility = View.VISIBLE } else { binding.tvDate.visibility = View.GONE binding.tvDay.visibility = View.GONE } } else { Log.d("MyLog", "Date is null") binding.tvDate.visibility = View.GONE binding.tvDay.visibility = View.GONE } if (!note.description.isNullOrEmpty()) { itemView.setOnClickListener { Log.d("MyLog", "Clicked on item") if (isAnim) { return@setOnClickListener } if (BottomList.visibility == View.GONE && tvDescription.text.isNotEmpty()) { Log.d("MyLog", "VISIBLE description") val expItem = Item val expHeight = BottomList expandView(expItem, expHeight, context) val animRotation = RotateAnimation( 0f, 180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f ) animRotation.duration = 500 animRotation.fillAfter = true ivArrow.startAnimation(animRotation) } else if (BottomList.visibility == View.VISIBLE) { Log.d("MyLog", "GONE description") val collItem = Item val collHeight = BottomList collHeight.visibility = View.GONE collapseView(collItem, collHeight) val animRotation = RotateAnimation( 180f, 0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f ) animRotation.duration = 250 animRotation.fillAfter = true ivArrow.startAnimation(animRotation) } } } itemView.setOnLongClickListener { listener.onLongClickItem(note, itemView) true } } private fun expandView(expItem: View, expHeight: View, context: Context) { isAnim = true val initHeight = expItem.height expHeight.measure( View.MeasureSpec.makeMeasureSpec(expItem.width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) val targetHeight = initHeight + expHeight.measuredHeight val animator = ValueAnimator.ofInt(initHeight, targetHeight) animator.addUpdateListener { animation -> val value = animation.animatedValue as Int val layoutParams = expItem.layoutParams layoutParams.height = value expItem.layoutParams = layoutParams } animator.duration = 200 animator.start() animator.addListener(object: AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) isAnim = false val animFadeIn = AnimationUtils.loadAnimation(context, R.anim.fade_in) expHeight.startAnimation(animFadeIn) expHeight.visibility = View.VISIBLE } }) } private fun collapseView(collItem: View, collHeight: View) { isAnim = true val initHeight = collItem.height collHeight.measure( View.MeasureSpec.makeMeasureSpec(collItem.width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) val targetHeight = initHeight - collHeight.measuredHeight val animator = ValueAnimator.ofInt(initHeight, targetHeight) animator.addUpdateListener { animation -> val value = animation.animatedValue as Int val layoutParams = collItem.layoutParams layoutParams.height = value collItem.layoutParams = layoutParams } animator.duration = 200 animator.start() animator.addListener(object: AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) isAnim = false } }) } //... companion object { fun create(parent: ViewGroup): ItemHolder { return ItemHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) ) } } } class ItemComparator : DiffUtil.ItemCallback<ItemsList>() { override fun areItemsTheSame(oldItem: ItemsList, newItem: ItemsList): Boolean { return oldItem.id == newItem.id } override fun areContentsTheSame(oldItem: ItemsList, newItem: ItemsList): Boolean { return oldItem == newItem } } }

При открытии фрагмента - он подлагивает из-за адаптера (блокируется поток, анимация открытия фрагмента из-за этого становится не плавной, рваной, а если элементов в списке много - то и вовсе пропускается), как мне это исправить? Я бы хотел, чтобы при открытии фрагмента, пока адаптер не загрузится, отображалась загрузка, а после готовности списка он отображался на экране, чтобы все это было без лагов.
Я почти уверен, что наделал ошибки в коде, может эффективнее использовать совсем другой подход? Много искал информацию про загрузку адаптера, но ничего не нашел, фрагмент все еще лагает. Прошу помощи, пожалуйста подскажите и дайте направление, в чем моя ошибка.

Дополнительно:

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Роман IT Ответ

Для реализации загрузки RecyclerView в приложении Android можно использовать адаптеры и менеджеры разметки.

Во-первых, необходимо создать класс адаптера, который будет преобразовывать данные в элементы, отображаемые в RecyclerView. Пример кода адаптера для RecyclerView в языке программирования Java:

public class MyAdapter extends RecyclerView.Adapter {
    private List mData;
 
    public MyAdapter(List data) {
        this.mData = data;
    }
 
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }
 
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String item = mData.get(position);
        holder.textView.setText(item);
    }
 
    @Override
    public int getItemCount() {
        return mData.size();
    }
 
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView textView;
 
        public ViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.text_view);
        }
    }
}

public class MyAdapter extends RecyclerView.Adapter { private List mData; public MyAdapter(List data) { this.mData = data; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false); ViewHolder viewHolder = new ViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { String item = mData.get(position); holder.textView.setText(item); } @Override public int getItemCount() { return mData.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView textView; public ViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.text_view); } } }

Затем необходимо создать макет элемента списка (item_layout.xml) с нужными элементами, например, TextView:

 

Далее, инициализируем RecyclerView в активности или фрагменте:

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List data = new ArrayList();
// добавляем данные в список
MyAdapter adapter = new MyAdapter(data);
recyclerView.setAdapter(adapter);

RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); List data = new ArrayList(); // добавляем данные в список MyAdapter adapter = new MyAdapter(data); recyclerView.setAdapter(adapter);

Теперь у вас должен отображаться список элементов в RecyclerView. Для загрузки данных по мере прокрутки можно использовать пагинацию или асинхронную загрузку данных.

Надеюсь, эта информация поможет вам реализовать загрузку RecyclerView в вашем приложении Android.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно