无法在回收者视图中正确显示项目分页问题

问题描述

用户滚动到末尾时尝试加载更多项目时,将显示删除进度对话框,然后再次显示,然后显示更多项目,但是仍未从回收者视图中删除进度对话框。有时会删除进度对话框,但仍然需要更多时间在回收者视图中显示更多项目。我正在使用firestore addOnSuccessListener从云Firestore检索项目并将其添加到arraylist,然后将高级广告添加到该arraylist并将数据添加到回收站适配器。

显示回收者视图项的活动MovieLists.java

public class MovieLists extends AppCompatActivity implements ItemInterface{

    //nothing important just a comment
    boolean runshowMovieOnce = true;
    Query mQuery;
    int loaderPosition;
    DocumentSnapshot lastVisible;
    String docId,catName,titleName;
    ItemInterface itemInterface;
    DatabaseReference listData;
    String VideoId;
    Movielistadapter movielistadapter;
    RecyclerView movieLists;

    // List of native ads that have been successfully loaded.
    private List<UnifiednativeAd> mNativeAds = new ArrayList<>();
    List<Object> itemDatas = new ArrayList<>();
    linearlayoutmanager layoutManager;
    // The number of native ads to load.
    public static final int NUMBER_OF_ADS = 2;

    // The AdLoader used to load ads.
    private AdLoader adLoader;
    int index = 2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_movie_lists);

        MaterialToolbar mToolBar = (MaterialToolbar) findViewById(R.id.imagePreviewToolbar);
        setSupportActionBar(mToolBar);
        docId = getIntent().getStringExtra("documentId");
        catName = getIntent().getStringExtra("catName");
        titleName = getIntent().getStringExtra("titleName");
        if (getSupportActionBar() != null) {
            getSupportActionBar().setdisplayHomeAsUpEnabled(true);
            getSupportActionBar().setHomeAsUpIndicator(R.drawable.back_button);
            getSupportActionBar().setTitle(titleName);
        }

        movieLists = (RecyclerView)findViewById(R.id.movie_lists);
        layoutManager = new linearlayoutmanager(this,linearlayoutmanager.VERTICAL,false);
        itemInterface = this;
        loadMovies();
    }

    @Override
    public void onFirebaseLoadSuccess(List<Object> itemDataList) {
        loadNativeAds();
    }

    @Override
    public void onFirebaseLoadFailed(String message) {

    }

    @SuppressLint("MissingPermission")
    private void loadNativeAds() {

        AdLoader.Builder builder = new AdLoader.Builder(this,"ca-app-pub-3940256099942544/8135179316");
        adLoader = builder.forUnifiednativeAd(
                new UnifiednativeAd.OnUnifiednativeAdLoadedListener() {
                    @Override
                    public void onUnifiednativeAdLoaded(UnifiednativeAd unifiednativeAd) {
                        // A native ad loaded successfully,check if the ad loader has finished loading
                        // and if so,insert the ads into the list.
                        mNativeAds.add(unifiednativeAd);
                        if (!adLoader.isLoading()) {
                            insertAdsInMenuItems();
                        }
                    }
                }).withAdListener(
                new AdListener() {
                    @Override
                    public void onAdFailedToLoad(int errorCode) {
                        // A native ad Failed to load,insert the ads into the list.
                        Log.e("MainActivity","The prevIoUs native ad Failed to load. Attempting to"
                                + " load another.");
                        if (!adLoader.isLoading()) {
                            insertAdsInMenuItems();
                        }
                    }
                }).build();

        // Load the Native ads.
        adLoader.loadAds(new AdRequest.Builder().build(),NUMBER_OF_ADS);
    }

    private void insertAdsInMenuItems() {
        if (mNativeAds.size() <= 0) {
            return;
        }
        int offset = 3;

        for (UnifiednativeAd ad : mNativeAds) {
            if (index<itemDatas.size()) {
                itemDatas.add(index,ad);
            }
            index = index + offset;
        }
        //index = itemDatas.size() - 3;

        if (runshowMovieOnce){
            showMoviesList();
        }
        runshowMovieOnce = false;
    }

    private void showMoviesList() {
        movieLists.setLayoutManager(layoutManager);
        movielistadapter = new Movielistadapter(movieLists,MovieLists.this,itemDatas);
        movieLists.setHasFixedSize(true);
        movieLists.setAdapter(movielistadapter);

        movielistadapter.setLoadMore(new ILoadMore() {
            @Override
            public void onLoadMore() {
                    itemDatas.add(null);

                movieLists.post(new Runnable() {
                    public void run() {
                        movielistadapter.notifyItemInserted(itemDatas.size() - 1);
                        Log.d("load position insert",""+(itemDatas.size()-1));
                    }
                });

                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {

                            itemDatas.remove(itemDatas.size()-1);
                            movielistadapter.notifyItemRemoved(itemDatas.size() - 1);
                            Log.d("load position rem",""+(itemDatas.size()-1));
                            int prevIoUsListSize = itemDatas.size();
                            Log.d("prevIoUsListSize",""+prevIoUsListSize);
                            loadMovies();
                            int newListSize = itemDatas.size();
                            Log.d("newListSize",""+newListSize);
                            movielistadapter.notifyDataSetChanged();
                            movielistadapter.setLoaded();

                        }
                    },5000);

            }
        });
    }

    private void loadMovies() {

        FirebaseFirestore mFirestore = FirebaseFirestore.getInstance();
        CollectionReference mPostsCollection = mFirestore.collection(catName).document(docId).collection("listItem");

        //Defining Query cursors
        if (lastVisible == null){
            mQuery = mPostsCollection.orderBy("pr",Query.Direction.ASCENDING)
                    .limit(6);
        }else {
            mQuery = mPostsCollection.orderBy("pr",Query.Direction.ASCENDING)
                    .startAfter(lastVisible)
                    .limit(6);
        }

        mQuery.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot documentSnapshots) {

                for (QueryDocumentSnapshot documentSnapshot : documentSnapshots){
                    ItemData itemData = documentSnapshot.toObject(ItemData.class);
                    itemDatas.add(itemData);
                    Log.d("movie name",itemData.getVn());
                }

                // Get the last visible document
                if (documentSnapshots.size() > 0)
                lastVisible = documentSnapshots.getDocuments()
                        .get(documentSnapshots.size() -1);

                onFirebaseLoadSuccess(itemDatas);
            }

        });
    }
}

Movielistadapter.java

public class Movielistadapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    List<Object> itemDatas;
    Context context;
    String urlStart = "https://i1.ytimg.com/vi/";
    String urlLast = "/mqdefault.jpg";
    private static final int MOVIE_ITEM_VIEW_TYPE = 0;
    private static final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
    private final int VIEW_TYPE_LOADING = 2;
    boolean isLoading;
    ILoadMore loadMore;
    int visibleThreshold ;
    int lastVisibleItem,totalItemCount;

    View itemV;

    public Movielistadapter(RecyclerView recyclerView,Context context,@NonNull List<Object> itemData) {
        this.itemDatas = itemData;
        this.context = context;
        final linearlayoutmanager linearlayoutmanager = (linearlayoutmanager)recyclerView.getLayoutManager();
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView,int dx,int dy) {
                super.onScrolled(recyclerView,dx,dy);
                    totalItemCount = linearlayoutmanager.getItemCount();
                    visibleThreshold = linearlayoutmanager.getChildCount();
                    lastVisibleItem = linearlayoutmanager.findLastVisibleItemPosition();
                    if (!isLoading && (visibleThreshold + lastVisibleItem) >= totalItemCount){
                        if (loadMore != null){
                            loadMore.onLoadMore();
                            isLoading = true;
                        }

                    }
            }
        });
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
        switch (viewType) {
            case UNIFIED_NATIVE_AD_VIEW_TYPE:
                View unifiednativeLayoutView = LayoutInflater.from(
                        parent.getContext()).inflate(R.layout.ad_unified,parent,false);
                return new UnifiednativeAdViewHolder(unifiednativeLayoutView);
            case VIEW_TYPE_LOADING:
                View viewL = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading,false);
                return new LoadingViewHolder(viewL);
            case MOVIE_ITEM_VIEW_TYPE:
                // Fall through.
            default: {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie_list,false);

                return new Movielistadapter.MovieListsMyViewHolder(view);
            }
        }
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder myViewHolder,int i) {
        //int viewType = getItemViewType(i);

        if (myViewHolder instanceof Movielistadapter.MovieListsMyViewHolder){
            MovieListsMyViewHolder movieListsMyViewHolder = (MovieListsMyViewHolder) myViewHolder;
            ItemData model = (ItemData)itemDatas.get(i);

            movieListsMyViewHolder.txt_item_title.setText(model.getVn());
            String urlImage = urlStart + model.getVi() + urlLast;
            Log.e("urlImage",urlImage);
            Glide.with(context)
                    .load(urlImage)
                    .placeholder(R.drawable.placeholder)
                    .error(R.drawable.placeholder)
                    .centerCrop()
                    .diskCacheStrategy(diskCacheStrategy.AUTOMATIC)
                    .into(movieListsMyViewHolder.img_title);

            movieListsMyViewHolder.setiItemClickListener(new IItemClickListener() {
                @Override
                public void onItemclickListener(View view,int position) {

                    ItemData itemData = new ItemData(model.getVi(),model.getVn(),model.getVd(),model.getPr(),model.getTc(),model.getVvc());
                    Log.d("Tmdb ID",String.valueOf(model.getTc()));
                    MovieDetails.startActivity(context,((MovieListsMyViewHolder) myViewHolder).transformationLayout,itemData);

                }
            });
        }else if (myViewHolder instanceof UnifiednativeAdViewHolder){
            Object recyclerViewItems = itemDatas.get(i);
            UnifiednativeAd nativeAd = (UnifiednativeAd) recyclerViewItems;
            populateNativeAdView(nativeAd,((UnifiednativeAdViewHolder) myViewHolder).getAdView());
        }else if (myViewHolder instanceof LoadingViewHolder){
            LoadingViewHolder loadingViewHolder = (LoadingViewHolder)myViewHolder;
            loadingViewHolder.progressBar.setIndeterminate(true);
        }
    }

    @Override
    public int getItemCount() {
        return itemDatas.size();
    }

    public class MovieListsMyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

        AppCompatTextView txt_item_title;
        ImageView img_title;
        IItemClickListener iItemClickListener;
        CardView itemCardView;
        TransformationLayout transformationLayout;

        public void setiItemClickListener(IItemClickListener iItemClickListener) {
            this.iItemClickListener = iItemClickListener;
        }

        public MovieListsMyViewHolder(@NonNull View itemView) {
            super(itemView);
            itemV = itemView;
            txt_item_title = (AppCompatTextView) itemView.findViewById(R.id.item_movie_Title);
            img_title = (ImageView)itemView.findViewById(R.id.item_movie_Image);
            //itemCardView = (CardView)itemView.findViewById(R.id.item_cardview);
            //itemCardView.setonClickListener(this);
            transformationLayout = (TransformationLayout)itemView.findViewById(R.id.transformationMovieLayout);
            transformationLayout.setonClickListener(this);
        }

        @Override
        public void onClick(View view){
            iItemClickListener.onItemclickListener(view,getAdapterPosition());
        }

    }

    private void populateNativeAdView(UnifiednativeAd nativeAd,UnifiednativeAdView adView) {
        // Some assets are guaranteed to be in every UnifiednativeAd.
        ((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
        ((TextView) adView.getBodyView()).setText(nativeAd.getBody());
        ((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());

        // These assets aren't guaranteed to be in every UnifiednativeAd,so it's important to
        // check before trying to display them.
        NativeAd.Image icon = nativeAd.getIcon();

        if (icon == null) {
            adView.getIconView().setVisibility(View.INVISIBLE);
        } else {
            ((ImageView) adView.getIconView()).setimageDrawable(icon.getDrawable());
            adView.getIconView().setVisibility(View.VISIBLE);
        }

        if (nativeAd.getPrice() == null) {
            adView.getPriceView().setVisibility(View.INVISIBLE);
        } else {
            adView.getPriceView().setVisibility(View.VISIBLE);
            ((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
        }

        if (nativeAd.getStore() == null) {
            adView.getStoreView().setVisibility(View.INVISIBLE);
        } else {
            adView.getStoreView().setVisibility(View.VISIBLE);
            ((TextView) adView.getStoreView()).setText(nativeAd.getStore());
        }

        if (nativeAd.getStarrating() == null) {
            adView.getStarratingView().setVisibility(View.INVISIBLE);
        } else {
            ((ratingBar) adView.getStarratingView())
                    .setrating(nativeAd.getStarrating().floatValue());
            adView.getStarratingView().setVisibility(View.VISIBLE);
        }

        if (nativeAd.getAdvertiser() == null) {
            adView.getAdvertiserView().setVisibility(View.INVISIBLE);
        } else {
            ((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
            adView.getAdvertiserView().setVisibility(View.VISIBLE);
        }

        // Assign native ad object to the native view.
        adView.setNativeAd(nativeAd);
    }
    @Override
    public int getItemViewType(int position) {
        //DocumentSnapshot itemData = getItem(position);
        Object recyclerViewItem = itemDatas.get(position);
        if (recyclerViewItem instanceof UnifiednativeAd) {
            return UNIFIED_NATIVE_AD_VIEW_TYPE;
        }else if (itemDatas.get(position) == null){
            return VIEW_TYPE_LOADING;
        }else {
            return MOVIE_ITEM_VIEW_TYPE;
        }
    }

    public void setLoadMore(ILoadMore loadMore){
        this.loadMore = loadMore;
    }

    private class LoadingViewHolder extends RecyclerView.ViewHolder {

        ProgressBar progressBar;

        public LoadingViewHolder(@NonNull View itemView) {
            super(itemView);
            progressBar = itemView.findViewById(R.id.progressBar);
        }
    }

    public void setLoaded(){
        isLoading = false;
    }

}

ScreenCapture of how recyclerview is displaying items

解决方法

短期答案:您的代码中发生了很多事情。如果只想删除loadingProgress,请在void viewsLoaded()的LoadingViewHolder内添加一个progressbar.setVisibility(View.GONE)方法,如果{Heller}不是,则在on if(myViewHolder instanceof LoadingViewHolder)的onBindViewHolder方法内,调用viewsLoaded()方法。定位为适配器上的最后一个。

长期答案:如果要提高性能,请阅读有关如何使用DiffUtil.ItemCallback<>而不是使用用于简单小型数据集的notifydatasetchanged()的信息。您在活动中有一个objectData列表,在适配器上有另一个,请阅读有关使用LiveData,数据绑定和MVVM模式的信息。

,

我建议您首先应该在Scroll View Listener中获得linearLayoutManager

另一个建议是不调用 movieListAdapter.notifyItemInserted(itemDatas.size() - 1);在Runnable内部进行异步,因为在将null添加到列表后,应通知适配器

itemsData.add(null);
movieListAdapter.notifyItemInserted(itemsData.size() - 1);

另一行在itemDatas.remove(itemDatas.size()-1)

从列表中删除项目后,列表大小将减小一。

所以这是正确的:

movieListAdapter.notifyItemRemoved(itemDatas.size());

我希望这些会有所帮助。