Reputation: 839
I am using multiple queries to fill a ReceyclerView however I keep getting the error E/RecyclerView: No adapter attached; skipping layout
the issue is not that I am not calling the RecyclerView
in OnCreate
since all of that code is in OnCreate
I have already checked that my RecyclerView
is my OnCreate
so it is not that.
Update:OnCreate
:
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.fragment, container, false);
final List<String> followingList = new ArrayList<>();
final List<Post> postList = new ArrayList<>();
final FollowerAdapter followerAdapter = new FollowerAdapter(postList);
final RecyclerView recyclerView = rootView.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getActivity(), RecyclerView.VERTICAL, false));
final LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) recyclerView.getLayoutManager());
recyclerView.setAdapter(followerAdapter);
Query first = userFollowingReference;//TODO Realtime updates
first.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull final Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
String id = document.getId();
followingList.add(id);
}
followerAdapter.notifyDataSetChanged();
if(!followingList.isEmpty()) {
Query second = rootRef.collection("posts/" + followingList.get(0) + "/userPosts")
.orderBy("date", Query.Direction.ASCENDING)
.limit(3);
second.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull final Task<QuerySnapshot> task) {
if(task.isSuccessful()) {
for(DocumentSnapshot document : task.getResult()){
Post post = document.toObject(Post.class);
postList.add(post);
}
followerAdapter.notifyDataSetChanged();
if(!postList.isEmpty()) {
lastVisible = task.getResult().getDocuments().get(task.getResult().size() - 1);
RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true;
}
}
@Override
public void onScrolled(final RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastVisible = task.getResult().getDocuments().get(task.getResult().size() - 1);
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
int visibleItemCount = linearLayoutManager.getChildCount();
int totalItemCount = linearLayoutManager.getItemCount();
if (isScrolling && (firstVisibleItemPosition + visibleItemCount == totalItemCount) && !isLastItemReached) {
isScrolling = false;
Query third = rootRef.collection("posts/" + followingList.get(task.getResult().size() - 1) + "/userPosts")
.orderBy("date", Query.Direction.ASCENDING)
.startAfter(lastVisible).limit(3);
third.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> t) {
if (t.isSuccessful()) {
for (DocumentSnapshot d : t.getResult()) {
Post post = d.toObject(Post.class);
postList.add(post);
}
followerAdapter.notifyDataSetChanged();
lastVisible = task.getResult().getDocuments().get(task.getResult().size() - 1);
if (t.getResult().size() < 3) {
isLastItemReached = true;
}
}
}
});
}
}
};
recyclerView.addOnScrollListener(onScrollListener);
}
}
}
});
}
}
}
});
return rootView;
}
Adapter:
class FollowerAdapter extends RecyclerView.Adapter<PostViewHolder> {
private List<Post> list;
FollowerAdapter(List<Post> list) {
this.list = list;
}
@NonNull
@Override
public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_layout, parent, false);
return new PostViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull PostViewHolder holder, int position) {
Post post = list.get(position);
holder.setPost(post);
}
@Override
public int getItemCount() {
return list.size();
}
}
When I run the app the RecyclerView
is empty and I get the error:
E/RecyclerView: No adapter attached; skipping layout
Also through debugging I found that the followingList
is being properly filled as is the list
that holds the posts. It looks as if The RecyclerView
is being skipped completely.
Edit: Here is my Firestore layout if that is helpful
Firestore-root
|
--- users (collection)
| |
| --- uid (documents)
| |
| --- name: "User Name"
| |
| --- email: "[email protected]"
|
--- following (collection)
| |
| --- uid (document)
| |
| --- userFollowing (collection)
| |
| --- uid (documents)
| |
| --- uid (documents)
|
--- posts (collection)
|
--- uid (documents)
|
--- userPosts (collection)
|
--- postId (documents)
|
--- postId (documents)
Thank you so far for everyone's help!
Update:
I am now able to see several posts but after scrolling to the bottom of the RecyclerView
I get java.lang.IndexOutOfBoundsException
Bellow is my Logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android,
java.lang.IndexOutOfBoundsException: Invalid index 2, size is 1
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.example.android.Fragments.FollowingFragment$1$1$1.onScrolled(FollowingFragment.java:104)
at androidx.recyclerview.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:5077)
at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:5241)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:549)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Upvotes: 0
Views: 79
Reputation: 1924
It seems that it's not finding any data on your RecyclerView on its initial layout pass. You should move your adapter set up outside of your OnCompleteListener
then update the data from within it:
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
// Your set up/initialization
recyclerView.setAdapter(yourAdapter);
first.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull final Task<QuerySnapshot> task){
// Update your adapter and notifyDataSetChanged when needed here
}
}
}
Upvotes: 1
Reputation: 1271
followerAdapter is passed with postlist , it should be followinglist.
Also in query2 postlist is currently not updating with fetched data
Upvotes: 1
Reputation: 1475
Suppose your data-parts are fine,
RecyclerView
needs these to display the content.
recyclerView.setLayoutManager(linearLayoutManager) // ?
recyclerView.setAdapter(...)
Make sure you call these method properly, and you can update if there's still problems.
Update:
I think your onComplete is not on the mainThread.
make sure you call recyclerView.setAdapter(followerAdapter);
from MainThread
.
in fact you can put setLayoutManager
and setAdapter
in onCreateView()
stage, just call notifyDataSetChanged
in your onComplete()
.
Upvotes: 1