简体   繁体   English

如何在应用启动时显示回收者视图?

[英]How to display recycler view on start of app?

I had tried to retrieve data from firebase database and show in recyclerview. 我曾尝试从Firebase数据库检索数据并在recyclerview中显示。 Everything is going perfect. 一切都进行得很完美。 Now in my firebase database has lots of node for recyclerview and each node has image link and now i just seen that recyclerview only show when all images are loaded from firebase database first. 现在,在我的Firebase数据库中,有很多用于recyclerview的节点,每个节点都有图像链接,现在我只看到recyclerview仅在首先从firebase数据库中加载所有图像时显示。 Database has a string and long both types of values. 数据库有一个字符串和long两种类型的值。 But No any text values display until all images are not loaded. 但是,直到未加载所有图像,才会显示任何文本值。 Here i shows what am i tried. 在这里,我展示了我的尝试。 So the question is how to show recyclerview step by step. 因此,问题在于如何逐步显示recyclerview。 if Text("string") is loaded than why it waiting for images loading? 如果要加载Text(“ string”),为什么要等待图像加载呢?

mAdapter = new PostAdapter(MainActivity.this);
query = PostRef
                    .orderByChild("timestamp")
                    .limitToLast(mPostsPerPage);
query.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                List<Post> userModels = new ArrayList<>();


                for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                    String o=userSnapshot.getKey();
                    userModels.add(userSnapshot.getValue(Post.class));
                }

                mAdapter.addAll(userModels);

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });

this is my adapter 这是我的适配器

public class PostAdapter extends RecyclerView.Adapter<PostHolder>
{
    List<Post> mPost;
    Context mContext;
    Boolean likecheck=false;

    public PostAdapter(Context c) {
        this.mPost  = new ArrayList<>();
        mContext=c;
    }

    @NonNull
    @Override
    public PostHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new PostHolder(LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.all_post_layout, viewGroup, false));

    }
@Override
    public void onBindViewHolder(@NonNull final PostHolder postHolder, final int i) {
        postHolder.setData(mPost.get(i));
        final String PostKey=mPost.get(i).getPostid();
        FirebaseAuth mAuth=FirebaseAuth.getInstance();
        final String currentUserID=mAuth.getCurrentUser().getUid();
        final DatabaseReference post=FirebaseDatabase.getInstance().getReference().child("Posts");
post.child(PostKey).child("postimg").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot)
            {
                if (dataSnapshot.exists())
                {
                    for (DataSnapshot dataSnapshot1:dataSnapshot.getChildren())
                    {
                        String postimagelink =dataSnapshot1.getValue().toString();
                        postimagelist.add(postimagelink);
                    }


                    String[] urls =postimagelist.toArray(new String[postimagelist.size()]);
                    postHolder.mPager.setAdapter(new SlidingImage_Adapter(mContext,urls));

                    postHolder.indicator.setViewPager(postHolder.mPager);

                    final float density = mContext.getResources().getDisplayMetrics().density;
                    postHolder.indicator.setRadius(5 * density);

                    postHolder.NUM_PAGES = urls.length;



                    postHolder.indicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
                    {

                        @Override
                        public void onPageSelected(int position) {
                            postHolder.currentPage = position;
                        }

                        @Override
                        public void onPageScrolled(int pos, float arg1, int arg2) {
                        }

                        @Override
                        public void onPageScrollStateChanged(int pos) {
                        }
                    });
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
@Override
    public int getItemCount() {
        return mPost.size();
    }
    public void addAll(List<Post> newPost) {
        int initialSize = mPost.size();
        mPost.addAll(newPost);
        notifyItemRangeInserted(initialSize, newPost.size());
    }

    public String getLastItemId() {
        return mPost.get(mPost.size() - 1).getPostid();
    }

}

viewholder 观看者

public class PostHolder extends RecyclerView.ViewHolder
{
    AutoLinkTextView description;
    TextView postfullname;
ViewPager mPager;
        int currentPage = 0;
        int NUM_PAGES = 0;
        CirclePageIndicator indicator;
        Context context;
public PostHolder(@NonNull View itemView) {
        super(itemView);

         postfullname = itemView.findViewById(R.id.user_post_full_name);
         description = itemView.findViewById(R.id.user_post_description);

         mPager = (ViewPager) itemView.findViewById(R.id.pager);
         indicator = (CirclePageIndicator)itemView.findViewById(R.id.indicator);

    }
    public void setData(Post post)
    {
        description.setText(post.getDescription());
        postfullname.setText(post.getFirstname()+" "+post.getLastname());
    }
}

在此处输入图片说明

Ok, I see a couple of problems with your adapter. 好的,我发现您的适配器有几个问题。

First 第一

 public void addAll(List<Post> newPost) {
        int initialSize = mPost.size();
        mPost.addAll(newPost);
        notifyItemRangeInserted(initialSize, newPost.size());
    }

Here, you are passing a list of Post as a parameter, you are using mPost.size() wich will not do anything there, the addAll method can be replaced with just add and the newPost.size() could be empty as well as the mPost.size() 在这里,您要传递一个Post列表作为参数,您正在使用mPost.size() ,在那儿什么也不做,addAll方法可以替换为add,而newPost.size()可以为空以及mPost.size()

Second 第二

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

You should also handle if the list is empty 如果列表为空,也应该处理

@Override
    public int getItemCount() {
        if(mPost.size() > 0){
          return mPost.size();
         }else{
           return 0;
           }
    }

Third 第三

All your firebase code inside your onBindViewHolder is wrong because while you are binding the data into each row, you are also trying to get each time the values with firebase. 您将onBindViewHolder内的所有onBindViewHolder代码都错了,因为将数据绑定到每一行时,您还试图每次使用firebase来获取值。 Doing this will lend to multiple firebase calls to get the data for just 1 row instead of getting all the data that you want to show. 这样做将导致多个firebase调用仅获取1行数据,而不是获取要显示的所有数据。

The solution of this is to do all your firebase logic in your main activity and pass the data to the adapter to set the values. 解决方案是在主要活动中执行所有Firebase逻辑,然后将数据传递给适配器以设置值。

To solve this with a more cleaner approach, pass your Array as a parameter in your Adapter Constructor, delete the addAll method and do this. 要使用更addAll方法解决此问题,请将Array作为参数传递给Adapter Constructor,删除addAll方法并执行此操作。

 public PostAdapter(Context c, List<Post> mPost) {
        this.mPost  = mPost
        mContext=c;
    }

Then as I said, delete all the firebase code from your onBindViewHolder and place it in your MainActivity 然后,正如我所说的,从onBindViewHolder删除所有onBindViewHolder代码,并将其放在MainActivity

With the constructor changed of your Adapter, you should now use your data fetched from firebase like this to work with your adapter. 更改适配器的构造函数后,您现在应该使用从firebase提取的数据来与适配器一起使用。

query = PostRef
                    .orderByChild("timestamp")
                    .limitToLast(mPostsPerPage);
query.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                List<Post> userModels = new ArrayList<>();


                for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
                    String o=userSnapshot.getKey();
                    userModels.add(userSnapshot.getValue(Post.class));
                }

                mAdapter = new PostAdapter(MainActivity.this,userModels)

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });

If you want to notify your adapter about any change. 如果您想将任何更改通知您的适配器。 Just make a global declaration of the adapter like 只需像这样对适配器进行全局声明

private PostAdapter adapter;

and then just use 然后就用

adapter.notifySetDataChanged(); 

Make sure the instance has been executed at least once. 确保实例至少已执行一次。

mAdapter = new PostAdapter(MainActivity.this,userModels);

Firebase has released firebaseRecyclerViewAdapter class. Firebase已发布firebaseRecyclerViewAdapter类。 This will do a lot of the work for you. 这将为您完成很多工作。

the adapter takes 4 input arguments: 适配器采用4个输入参数:

  • Object class 对象类别
  • List item layout resource 列表项布局资源
  • Viewholder Class 观看者类别
  • Query/firebase reference 查询/ firebase参考

the populateViewHolder method is all that will be required 仅需populateViewHolder方法

FirebaseRecyclerViewAdapter<Object, ObjectViewHolder> adapter = new FirebaseRecyclerViewAdapter<Object, ObjectViewHolder>
(Object.class, android.R.layout.*list_item_layout*, ObjectViewHolder.class, objectQuery) {
    public void populateViewHolder(ObjectViewHolder ObjectViewHolder, Object Object) {

    //populate your views, example:
        ObjectViewHolder.textview.setText(object.getTextOne());

    }
};

Then set the adapter: 然后设置适配器:

recycler.setAdapter(mAdapter);

More info on this Firebase RecyclerView Adapter 关于此Firebase RecyclerView适配器的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM