【问题标题】:Stop RecyclerView from reloading data停止 RecyclerView 重新加载数据
【发布时间】:2018-03-31 18:59:59
【问题描述】:

嗨,我需要在向上滚动时停止 RecyclerView 重新加载数据,但我不知道如何 :( 我搜索它但我找不到任何答案

适配器: mPostAdapterNew

RecyclerView : MPostRV_new

那么你们能帮帮我吗?在此先感谢:D

编辑:这是我的代码:

    private void setupAdaptaterNew() {
    mPostAdapterNew = new FirebaseRecyclerAdapter<Post, PostViewHolder>(
            Post.class,
            R.layout.item_layout_evenimente,
            PostViewHolder.class,
            mPostRef
    ) {

        @Override
        public void populateViewHolder(final PostViewHolder viewHolder, final Post model, final int position) {
            final long EndZi = viewHolder.setEndZi(model.getEndZi());
            final int EndLuna = viewHolder.setEndLuna(model.getEndLuna());
            final int EndAn = viewHolder.setEndAn(model.getEndAn());
            Calendar cal = Calendar.getInstance();
            final Button btnAddEvent = viewHolder.itemView.findViewById(R.id.BtnParticip);
            final Button btnDeleteEvent = viewHolder.itemView.findViewById(R.id.BtnNuParticip);
            final int EndOra = viewHolder.setEndOra(model.getEndOra());
            final int EndMinute = viewHolder.setEndMinute(model.getEndMinute());
            final String headline = viewHolder.setHeadline(model.getHeadline());
            final String locatie = viewHolder.setStrada(model.getStrada());
            final String organizator = viewHolder.setOrganizator(model.getOrganizator());
            final String descriere = viewHolder.setPostDescriere(model.getDescriere());
            final ContentResolver cr = getActivity().getContentResolver();
            final ContentValues values = new ContentValues();
            final ContentResolver crReminder = getActivity().getContentResolver();
            final ContentValues valuesReminder = new ContentValues();
            final Uri event = null;
            final TextView nr_persoane = viewHolder.itemView.findViewById(R.id.nr_persoane);
            final String key = this.getRef(position).getKey();
            final Cursor data = mDatabaseHelper.getData();

            cal.set(Calendar.HOUR, 24);
            cal.set(Calendar.MINUTE, 59);
            cal.set(Calendar.MILLISECOND, 0);
            cal.set(Calendar.MONTH, EndLuna);
            cal.set(Calendar.DAY_OF_MONTH, (int) EndZi);
            cal.set(Calendar.YEAR, EndAn);


            if (Calendar.getInstance().before(cal)) {
                StorageReference storageReference = FirebaseStorage.getInstance().getReferenceFromUrl(model.getImageUrl());
                Glide.with(Fragment_events_new.this)
                        .using(new FirebaseImageLoader())
                        .load(storageReference)
                        .asBitmap()
                        .centerCrop()
                        .into(new SimpleTarget<Bitmap>() {
                            @Override
                            public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                                viewHolder.postIV.setImageBitmap(resource);
                            }
                        });


                viewHolder.setHeadline(model.getHeadline());
                viewHolder.setZiua(model.getZiua());
                viewHolder.setLuna(model.getLuna());
                viewHolder.setOra(model.getOra());
                viewHolder.setOrganizator(model.getOrganizator());
                viewHolder.setCategoria(model.getCategoria());
                viewHolder.setStrada(model.getStrada());
                viewHolder.setLocalitatea(model.getLocalitatea());
                viewHolder.setPostDescriere(model.getDescriere());
                viewHolder.setNrPersoane(model.getNrPeople());
            } else {
                viewHolder.itemView.setVisibility(View.GONE);
                viewHolder.itemView.setLayoutParams(new RecyclerView.LayoutParams(0, 0));
            }

            btnAddEvent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED ||
                            ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(getActivity(), "Permisii insuficiente.\n Va rugam sa activati permisiunea de CALENDAR", Toast.LENGTH_LONG).show();
                        NoPermissions();
                    } else {
                        addEvent(values, EndZi, EndAn, EndLuna, EndOra, EndMinute, headline, descriere, locatie, organizator, event, cr, valuesReminder, crReminder);
                        int i = viewHolder.setNrPersoane(model.getNrPeople()) + 1;
                        nr_persoane.setText(String.valueOf(i));
                        mPostRef.child(key).child("nrPeople").setValue(i);
                    }
                }
            });

            btnDeleteEvent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    deleteEvent(data, headline);
                    btnAddEvent.setVisibility(View.VISIBLE);
                    btnDeleteEvent.setVisibility(View.GONE);
                    int i = viewHolder.setNrPersoane(model.getNrPeople()) - 1;
                    nr_persoane.setText(String.valueOf(i));
                    mPostRef.child(key).child("nrPeople").setValue(i);
                }
            });

            if (CheckDB(headline)) {
                btnAddEvent.setVisibility(View.GONE);
                btnDeleteEvent.setVisibility(View.VISIBLE);
            } else {
                btnAddEvent.setVisibility(View.VISIBLE);
                btnDeleteEvent.setVisibility(View.GONE);
            }
        }
    };

}

@SuppressLint("MissingPermission")
private void addEvent(ContentValues values, float EndZi, int EndAn, int EndLuna, int EndOra, int EndMinute,
                      String headline, String descriere, String locatie, String organizator,
                      Uri event, ContentResolver cr, ContentValues valuesReminder, ContentResolver crReminder) {
    long startMillis = 0;
    long endMillis = 0;


    Calendar beginTime = Calendar.getInstance();
    beginTime.set(EndAn, EndLuna, (int) EndZi, EndOra, EndMinute);
    startMillis = beginTime.getTimeInMillis();
    Calendar endTime = Calendar.getInstance();
    endTime.set(EndAn, EndLuna, (int) EndZi, EndOra, EndMinute);
    endMillis = endTime.getTimeInMillis();
    //Add Values
    values.put(CalendarContract.Events.DTSTART, startMillis);
    values.put(CalendarContract.Events.TITLE, headline);
    values.put(CalendarContract.Events.DESCRIPTION, descriere); //TODO change description here!
    TimeZone timeZone = TimeZone.getDefault();
    values.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone.getID());
    values.put(CalendarContract.Events.CALENDAR_ID, 1);
    values.put(CalendarContract.Events.DTEND, endMillis);
    values.put(CalendarContract.Events.EVENT_LOCATION, locatie);
    values.put(CalendarContract.Events.ORGANIZER, organizator);
    event = cr.insert(CalendarContract.Events.CONTENT_URI, values);
    valuesReminder.put(CalendarContract.Reminders.DTSTART, startMillis);
    Uri REMINDERS_URI_DAY = Uri.parse(getCalendarUriBase(true) + "reminders");
    valuesReminder = new ContentValues();
    valuesReminder.put("event_id", Long.parseLong(event.getLastPathSegment()));
    valuesReminder.put("method", 1);
    valuesReminder.put("minutes", 1440);

    Uri uriReminderDay = crReminder.insert(REMINDERS_URI_DAY, valuesReminder);
    Uri REMINDERS_URI_HOUR = Uri.parse(getCalendarUriBase(true) + "reminders");
    valuesReminder = new ContentValues();
    valuesReminder.put("event_id", Long.parseLong(event.getLastPathSegment()));
    valuesReminder.put("method", 1);
    valuesReminder.put("minutes", 120);
    Uri uriReminder = crReminder.insert(REMINDERS_URI_HOUR, valuesReminder);

    createDialog(headline, "Ati adaugat evenimentul in calendar!");
    String event_id = String.valueOf(Long.parseLong(event.getLastPathSegment()));
    AddData(headline, event_id);
}

private void deleteEvent(Cursor data, String headline) {
    while (data.moveToNext()) {
        if (data.getString(1).equals(headline)) {
            Uri deleteUri = null;
            deleteUri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, Long.parseLong(data.getString(2)));
            int rows = getActivity().getContentResolver().delete(deleteUri, null, null);
            createDialog(headline, "Ati sters evenimentu din calendar!");
            mDatabaseHelper.deleteData(headline, data.getString(2));

        }
    }
}

private boolean CheckDB(String headline) {
    Cursor data = mDatabaseHelper.getData();
    while (data.moveToNext()) {
        if (data.getString(1).equals(headline)) {
            return true;
        }
    }
    return false;
}

【问题讨论】:

  • “停止重新加载数据”是什么意思?您的意思是滚动锁定在当前可见项目上吗?
  • 所以我有一个 recyclerView whit 数据,然后我想向上滚动滚动不流畅,我看到在 android 控制台中,来自 RecyclerView 的值重新加载来自适配器的数据并且滚动是在刷新/重新加载完成之前不平滑
  • 也许你加载了太多的项目(或者项目太复杂),如果没有任何代码示例来帮助你,很难判断
  • @AntonMakov 我已经添加了代码,但我认为我为每个结果做了太多的事情,因为我还有一个适配器,但我没有那么多代码:)
  • 在创建适配器之前,您需要获取数据(从数据库/网络或其他来源中提取数据)。缓慢来自这样一个事实,即每次滚动列表时,它都需要从源 db/web 读取/获取数据填充数据并创建列表项的视图 => 耗时过多,这就是为什么它非常慢

标签: android android-recyclerview


【解决方案1】:

您好,我在这里遇到了同样的问题,特别是如果我必须将像图像一样的媒体加载到 RecyclerView 使用一点大 缓存 为我解决了问题,你在这里

MPostRV_new=view.findViewById(R.id.your_layout);
MPostRV_new.setHasFixedSize(true);
MPostRV_new.setLayoutManager(new LinearLayoutManager(getContext()));
MPostRV_new.setItemAnimator(null);
MPostRV_new.setItemViewCacheSize(50);

有关更多信息,请查看此资源 setItemViewCacheSize

【讨论】:

    【解决方案2】:

    基本上你需要为你的回收视图适配器创建一个类(你应该使用 recycleview 而不是使用 listview,因为它比 listview 更新,并且有许多 listview 没有的优化和新功能)。

    MyRecyclerViewAdapter

    public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> {
    private List<FeedItem> feedItemList;
    private Context mContext;
    
    public MyRecyclerViewAdapter(Context context, List<FeedItem> feedItemList) {
        this.feedItemList = feedItemList;
        this.mContext = context;
    }
    
    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
        CustomViewHolder viewHolder = new CustomViewHolder(view);
        return viewHolder;
    }
    
    @Override
    public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
        FeedItem feedItem = feedItemList.get(i);
    
        //Render image using Picasso library
        if (!TextUtils.isEmpty(feedItem.getThumbnail())) {
            Picasso.with(mContext).load(feedItem.getThumbnail())
                    .error(R.drawable.placeholder)
                    .placeholder(R.drawable.placeholder)
                    .into(customViewHolder.imageView);
        }
    
        //Setting text view title
        customViewHolder.textView.setText(Html.fromHtml(feedItem.getTitle()));
    }
    
    @Override
    public int getItemCount() {
        return (null != feedItemList ? feedItemList.size() : 0);
    }
    
    class CustomViewHolder extends RecyclerView.ViewHolder {
        protected ImageView imageView;
        protected TextView textView;
    
        public CustomViewHolder(View view) {
            super(view);
            this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
            this.textView = (TextView) view.findViewById(R.id.title);
        }
    }
    

    }

    正如您在上面的示例中看到的,所有项目都已获取(准备好显示,而不是每次用户向上/向下滚动列表时获取它们)。其次,有一些函数,如 onCreateViewHolder,您需要在其中创建自己的视图持有者(膨胀布局并从中创建一个持有者,该持有者将保存所有视图,这些视图将用于显示您想要在列表中显示的数据) .第二个 onBindViewHolder 用于将持有者中的视图与适配器从其构造函数获取的数据绑定(连接)。

    实现适配器后,您应该按如下方式使用它: 在你的活动/片段中的某个地方

    ...
    List<FeedItem> data = manager.getItems();
    MyRecyclerViewAdapter adapter = new MyRecyclerViewAdapter(MainActivity.this, feedsList);
    mRecyclerView.setAdapter(adapter);
    ...
    

    这里有几点需要注意: 1) manager.getItems();是一个经理,您可以从那里获取您的项目,为了使用它,您需要知道您需要从哪里获取这些项目(网络/存储或其他来源)然后您需要实施它(有很多网站解释怎么做。 2)如果您使用的是片段,您应该使用而不是 MainActivity.this getActivity()

    更多详情可以看here

    希望它能帮助您了解如何操作。

    【讨论】:

      【解决方案3】:

      使用RecyclerView作为组件的意义在于,它会在每次滚动时重建可见项,以便加载数据,您无法“阻止”它。

      您有两种选择:

      1. 检查您是否有长时间运行的操作(即,您每次都查询网络或您的查看器具有大图像和复杂结构)。尝试对其进行优化,例如存储来自网络查询的数据或调整图片大小

      2. 使用ListView。它会立即加载所有项目,然后如果您仅显式调用更新,它将更新。

      【讨论】:

      • 我从数据库中加载我的图片 url 并且布局上的大小是 90/90 。在列表视图中我也可以使用图像吗?
      • 您查询的这个数据库是内部的还是外部的?一些具有大量图像的应用程序使用空容器来存储图片,因此用户不必等待图片加载后就可以赶上其余的布局。是的,listview 看起来完全一样,看看vogella.com/tutorials/AndroidListView/article.html
      • 从 Firebase 外部
      • 好的,有一个类似的问题是,firebase 图像加载到回收器中的速度太慢,导致滚动不流畅。要回答您提出的问题,您不能停止重新加载回收站。要走的路是listview。但是你可以用不同的方式解决这个问题。试着看看为什么你的图片加载太慢,如何让它更快,然后它会让回收器更顺畅。例如stackoverflow.com/questions/26856487/…
      • 我不认为它来自图像,因为我有另一个适配器,它的图像多 5 倍,而且滚动很流畅
      猜你喜欢
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 2014-07-21
      • 2017-07-19
      • 1970-01-01
      • 2014-09-15
      相关资源
      最近更新 更多