Reputation: 98
I'm getting an error E/RecyclerView: No adapter attached; skipping layout
while using FirestoreRecylerAdapter INSIDE a FRAGMENT. After reading all answers to similar questions ,I'm not able to reach to a solution because most of them are for recylerAdapter inside activiy, i.e. they have an onCreate method where they can set up their adapter first. In fragments as you know,there is no view in onCreate method so I can't find my recyclerView there.Some answers are suggesting to setup an empty adapter and then notify for data change.
I'm not able to able to setup an empty adapter in onCreateView. Here's my code:
My adapter:
package com.example.XX;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.firebase.ui.firestore.FirestoreRecyclerAdapter;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
public class ProfileRecyclerAdapter extends FirestoreRecyclerAdapter<Profile,ProfileRecyclerAdapter.ProfileViewHolder> {
public ProfileRecyclerAdapter(@NonNull FirestoreRecyclerOptions<Profile> options) {
super(options);
}
@Override
protected void onBindViewHolder(@NonNull ProfileViewHolder holder, int position, @NonNull Profile profile) {
holder.Name_textView.setText(profile.getName());
holder.Sector_textView.setText(profile.getSector());
holder.Pincode_textView.setText(profile.getPincode());
}
@NonNull
@Override
public ProfileViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater=LayoutInflater.from(parent.getContext());
View view=layoutInflater.inflate(R.layout.profile_row_item,parent,false);
return new ProfileViewHolder(view);
}
class ProfileViewHolder extends RecyclerView.ViewHolder{
TextView Name_textView;
TextView Sector_textView;
TextView Pincode_textView;
public ProfileViewHolder(@NonNull View itemView) {
super(itemView);
Name_textView=itemView.findViewById(R.id.Name_textView);
Sector_textView=itemView.findViewById(R.id.Sector_textView);
Pincode_textView=itemView.findViewById(R.id.Pincode_textView);
}
}
}
My FRAGMENT where I want the data to be displayed:
package com.example.XX;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.List;
public class MainQueryFragment extends Fragment {
RecyclerView recyclerView;
ProfileRecyclerAdapter profileRecyclerAdapter;
TextView yourSector;
TextView yourPincode;
FirebaseFirestore db = FirebaseFirestore.getInstance();
String tuserID = FirebaseAuth.getInstance().getCurrentUser().getUid();
String customerPincode;
String customerSector;
String sectorText;
String pincodeText;
String[] testArray;
String name;
String pincode;
String address;
String mobileNumber;
String sector;
String avgDeliveryTime;
String avgDeliveryTimeUrg;
Boolean item1;
Boolean item2;
Boolean item3;
Boolean item4;
Boolean item5;
Boolean item6;
Boolean item7;
Boolean item8;
Boolean item9;
Boolean item10;
String speciality;
String avgNumOrders;
String shopType;
String userID;
String avgPriceRange;
String education;
Button button;
public MainQueryFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main_query, container, false);
yourSector = view.findViewById(R.id.Sector_tv);
yourPincode = view.findViewById(R.id.Pincode_tv);
recyclerView = view.findViewById(R.id.recyclerView_Profile);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(profileRecyclerAdapter);
{ DocumentReference docRef = db.collection("customerUsers").document(tuserID);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
customerPincode = document.getString("pincode");
customerSector = document.getString("sector");
sectorText = "Sector : " + customerSector;
pincodeText = "Pincode : " + customerPincode;
yourSector.setText(sectorText);
yourPincode.setText(pincodeText);
Log.d("work", "onComplete: " + customerPincode);
} else {
Log.d("docref", "No such document");
}
} else {
Log.d("docref", "get failed with ", task.getException());
}
}
});
}//doc for sector,pincode loading
if (getArguments() != null) {
MainQueryFragmentArgs args = MainQueryFragmentArgs.fromBundle(getArguments());
testArray = args.getArrayCheckboxData();
}
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
button=view.findViewById(R.id.startQuery_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Query query = FirebaseFirestore.getInstance()
.collection("tUsers")
.whereEqualTo("pincode", customerPincode)
.whereEqualTo("sector", customerSector)
.whereEqualTo(testArray[0], true)
.whereEqualTo(testArray[1], true)
.whereEqualTo(testArray[2], true)
.whereEqualTo(testArray[3], true);
FirestoreRecyclerOptions<Profile> options = new FirestoreRecyclerOptions.Builder<Profile>()
.setQuery(query,Profile.class)
.build();
profileRecyclerAdapter = new ProfileRecyclerAdapter(options);
recyclerView.setAdapter(profileRecyclerAdapter);
profileRecyclerAdapter.startListening();
}
});
}
}
Even if I comment out my button and onclicklistener and then run the app,I should be technically running an empty adapter. Still I'm getting the same error. Please suggest what i should do,keeping in mind I CANNOT use onCreate
Edit Here is my edited code. Now I'm getting null Pointer exception and my app is crashing:
package com.example.XX;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.firebase.ui.firestore.FirestoreRecyclerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.List;
public class MainQueryFragment extends Fragment {
RecyclerView recyclerView;
ProfileRecyclerAdapter profileRecyclerAdapter;
TextView yourSector;
TextView yourPincode;
FirebaseFirestore db = FirebaseFirestore.getInstance();
String tuserID = FirebaseAuth.getInstance().getCurrentUser().getUid();
String customerPincode;
String customerSector;
String sectorText;
String pincodeText;
String[] testArray;
String name;
String pincode;
String address;
String mobileNumber;
String sector;
String avgDeliveryTime;
String avgDeliveryTimeUrg;
Boolean item1;
Boolean item2;
Boolean item3;
Boolean item4;
Boolean item5;
Boolean item6;
Boolean item7;
Boolean item8;
Boolean item9;
Boolean item10;
String speciality;
String avgNumOrders;
String shopType;
String userID;
String avgPriceRange;
String education;
Button button;
public MainQueryFragment() {
// Required empty public constructor
}
@Override
public void onStart() {
super.onStart();
profileRecyclerAdapter.startListening();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main_query, container, false);
yourSector = view.findViewById(R.id.Sector_tv);
yourPincode = view.findViewById(R.id.Pincode_tv);
{ DocumentReference docRef = db.collection("customerUsers").document(tuserID);
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
customerPincode = document.getString("pincode");
customerSector = document.getString("sector");
sectorText = "Sector : " + customerSector;
pincodeText = "Pincode : " + customerPincode;
yourSector.setText(sectorText);
yourPincode.setText(pincodeText);
Log.d("work", "onComplete: " + customerPincode);
} else {
Log.d("docref", "No such document");
}
} else {
Log.d("docref", "get failed with ", task.getException());
}
}
});
}//doc for sector,pincode loading
if (getArguments() != null) {
MainQueryFragmentArgs args = MainQueryFragmentArgs.fromBundle(getArguments());
testArray = args.getArrayCheckboxData();
}
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
button=view.findViewById(R.id.startQuery_button);
recyclerView = view.findViewById(R.id.recyclerView_Profile);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Query query = FirebaseFirestore.getInstance()
.collection("tUsers")
.whereEqualTo("pincode", customerPincode)
.whereEqualTo("sector", customerSector)
.whereEqualTo(testArray[0], true)
.whereEqualTo(testArray[1], true)
.whereEqualTo(testArray[2], true)
.whereEqualTo(testArray[3], true);
FirestoreRecyclerOptions<Profile> options = new FirestoreRecyclerOptions.Builder<Profile>()
.setQuery(query,Profile.class)
.build();
profileRecyclerAdapter = new ProfileRecyclerAdapter(options);
recyclerView.setAdapter(profileRecyclerAdapter);
pailorProfileRecyclerAdapter.notifyDataSetChanged();
}
});
}
@Override
public void onStop() {
super.onStop();
profileRecyclerAdapter.stopListening();
}
}
Upvotes: 0
Views: 318
Reputation: 1
Instead of using adapter.startListening and
adapter.stopListening use .setLifecycleOwner(this)
Check out this working code:
FirestoreRecyclerOptions<Profile> options = new FirestoreRecyclerOptions.Builder<Profile>()
.setQuery(query,Profile.class)
.setLifecycleOwner(this)
.build();
profileRecyclerAdapter = new ProfileRecyclerAdapter(options);
recyclerView.setAdapter(profileRecyclerAdapter)
Upvotes: 0
Reputation: 13129
When you first create your Adapter in onCreateView()
, you are not initializing that adapter, instead, you are setting the adapter right from the property:
ProfileRecyclerAdapter profileRecyclerAdapter;
recyclerView.setAdapter(profileRecyclerAdapter);
You need to initialize your adapter to set that adapter to your RecyclerView.
Second, you should not have that asynchronous call inside your onCreateView()
, instead, use onViewCreated()
to handle your asynchronous calls after your view is created.
Then, you are also making your adapter instance in your onViewCreated()
with:
FirestoreRecyclerOptions<Profile> options = new FirestoreRecyclerOptions.Builder<Profile>()
.setQuery(query,Profile.class)
.build();
profileRecyclerAdapter = new ProfileRecyclerAdapter(options);
recyclerView.setAdapter(profileRecyclerAdapter);
profileRecyclerAdapter.startListening();
And you should do:
profileRecyclerAdapter.startListening();
In your onStart()
and profileRecyclerAdapter.stopListening();
at your onStop()
Upvotes: 1