I have used FirbaseRecyclerAdapter but i am getting trouble to finding the value of child following is the code i have used
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
Toast.makeText(this, "Created", Toast.LENGTH_SHORT).show();
listitems = new ArrayList<>();
databaseReference = FirebaseDatabase.getInstance().getReference().child("content");
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<Listitem ,BlogViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Listitem, BlogViewHolder>(
Listitem.class,R.layout.list_item,BlogViewHolder.class,databaseReference
) {
#Override
protected void populateViewHolder(BlogViewHolder viewHolder, Listitem model, int position) {
viewHolder.sethead(model.getHead());
viewHolder.setdesc(model.getDesc());
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
There is an extra -L7n...Udk3D key under duck, which is most likely the reason that your Listitem model class can't look up the head and description properties. To fix it, get rid of the extra -L7n...Udk3D key.
Related
In my app there is an activity that when it opens it should display data in a RecyclerView. The data is stored in a collection in Firestore but unfortunately it is only working for API 21, 22 and 23, everything above is not displaying the data (see screenshots). Also sometimes it is not showing the data on the first time the user opens the activity, only when he opens it a second time or logs out and in again (in API 21). Is this something that is known or is there something with my code? Or is there a better way to display the data of a collection in a RecyclerView?
I also noticed a strange behavior:
When I add an EditText to the layout without doing anything with it in the activity, when the user clicks on the EditText, the desired documents are then displayed as they should be. On the emulator running API 21, the data shows without having to click on the EditText, so the mentioned behavior applies for API greater 24. Can someone explain this behavior?
Any help is much appreciated!
I followed this tutorial where everything works fine:
https://www.youtube.com/watch?v=lAGI6jGS4vs
My app only targets API starting at 21.
Here is my activity with the RecyclerView:
public class PrizeGameActivity extends AppCompatActivity {
private Toolbar mToolbar;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference prizesRef = db.collection("Prizes");
private PrizeGameAdapter prizeGameAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prize_game);
// Sets the custom toolbar as ActionBar
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
setUpRecyclerView();
}
private void setUpRecyclerView() {
Query query = prizesRef.orderBy("text",Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Prizes> options = new FirestoreRecyclerOptions.Builder<Prizes>()
.setQuery(query, Prizes.class)
.build();
prizeGameAdapter = new PrizeGameAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view_prize_game);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(prizeGameAdapter);
prizeGameAdapter.startListening();
}
#Override
protected void onStart() {
super.onStart();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
#Override
protected void onStop() {
super.onStop();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
// Makes a left to right animation when user clicks the back button of the toolbar
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return false;
}
// Makes a right left animation when clicking the back button
#Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}
}
Here is my Adapter:
public class PrizeGameAdapter extends FirestoreRecyclerAdapter<Prizes, PrizeGameAdapter.PrizeGameHolder> {
public PrizeGameAdapter(#NonNull FirestoreRecyclerOptions<Prizes> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull PrizeGameHolder holder, int position, #NonNull Prizes model) {
holder.textViewPrizeGame.setText(model.getText());
}
#NonNull
#Override
public PrizeGameHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_prize_game,parent, false);
return new PrizeGameHolder(view);
}
class PrizeGameHolder extends RecyclerView.ViewHolder {
TextView textViewPrizeGame;
public PrizeGameHolder(#NonNull View itemView) {
super(itemView);
textViewPrizeGame = itemView.findViewById(R.id.listitem_text_view_prize_game);
}
}
}
And here is my prizes class:
public class Prizes {
public Prizes (){
}
public String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Prizes(String text) {
this.text = text;
}
}
I managed to get the desired result by adding a OnCompleteListener and then set up the RecyclerView. Here is the code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prize_game);
Query query = prizesRef.orderBy("text",Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Prizes> options = new FirestoreRecyclerOptions.Builder<Prizes>()
.setQuery(query, Prizes.class)
.build();
prizeGameAdapter = new PrizeGameAdapter(options);
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
setUpRecyclerView();
}else {
}
}
});
}
private void setUpRecyclerView() {
RecyclerView recyclerView = findViewById(R.id.recycler_view_prize_game);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(prizeGameAdapter);
prizeGameAdapter.startListening();
}
#Override
protected void onStart() {
super.onStart();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
#Override
protected void onStop() {
super.onStop();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
For example, I'd like to display all orders that has fs_ID equal to FS02. I provided a screenshot of my firebase below:
This is my current code:
public class NewOrders extends AppCompatActivity {
public RecyclerView recyclerView;
public RecyclerView.LayoutManager layoutManager;
FirebaseDatabase database;
DatabaseReference requests;
FirebaseRecyclerAdapter<Request, OrderViewHolder> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_orders);
//Firebase
database = FirebaseDatabase.getInstance();
requests = database.getReference("Order_Header");
recyclerView = findViewById(R.id.listOrders);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
adapter = new FirebaseRecyclerAdapter<Request, OrderViewHolder>(
Request.class,
R.layout.order_layout,
OrderViewHolder.class,
requests.orderByChild("fs_ID")
.equalTo("FS02")
) {
#Override
protected void populateViewHolder(OrderViewHolder viewHolder, Request model, int position) {
viewHolder.txtOrderID.setText(adapter.getRef(position).getKey());
viewHolder.txtOrderStatus.setText(convertCodeToStatus(model.getStatus()));
viewHolder.txtOrderUsername.setText(model.getUsername());
viewHolder.txtOrderFname.setText(model.getFirstName());
viewHolder.txtOrderLname.setText(model.getLastName());
viewHolder.txtOrderEmail.setText(model.getEmail());
viewHolder.txtOrderAddress.setText(model.getAddress());
}
};
recyclerView.setAdapter(adapter);
}
private String convertCodeToStatus(String status){
//pasok db how
if (status.equals("OS1")) {
return "Placed";
}
else if (status.equals("OS2")) {
return "In progress";
}
else {
return "OS3";
}
}
}
The screen where it is suppose to show is empty, what might be the problem? Thanks
You seem to not be calling startListening anywhere, which is required for FirebaseUI to start observing the database. Right now you told the adapter what data to observe, and what to do with it, but you never told it to start doing so.
You'll typically want to start listening in the onStart of your activity, and then stop listening in onStop().
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
Also see the FirebaseUI documentation on the adapter lifecycle.
The code Below I seem to have done everything needed, but the recyclerview is just not being populated.
I even put the Log on OnDateChange to see if it's called, and it was called once on the LogCat after I ran it on my Galaxy S6. Also, the database is public.
RecyclerView chat_view;
EditText message_text;
CollectionReference reference = FirebaseFirestore.getInstance().collection("stage2");
Query query = reference.orderBy("timestamp");
FirestoreRecyclerAdapter<ChatMessage,ChatHolder> adapter=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//initializing, called below
init();
}
private FirestoreRecyclerAdapter<ChatMessage,ChatHolder> newAdapter() {
final FirestoreRecyclerOptions options = new FirestoreRecyclerOptions.Builder<ChatMessage>()
.setQuery(query,ChatMessage.class)
.setLifecycleOwner(this)
.build();
return new FirestoreRecyclerAdapter<ChatMessage, ChatHolder>(options) {
#Override
public ChatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item,parent,false);
//if(((ChatMessage)options.getSnapshots().getSnapshot(viewType)).)
return new ChatHolder(view);
}
#Override
protected void onBindViewHolder(ChatHolder holder, int position, ChatMessage model) {
//displaying the message and users into the recyclerview
holder.user_msg.setText(model.getMessage());
holder.user_date.setText(model.getDate());
holder.user_name.setText(model.getName());
}
#Override
public void onDataChanged() {
Log.d("TAG", "YESSIR");
}
#Override
public void onError(FirebaseFirestoreException e) {
super.onError(e);
}
};
}
private void init(){
chat_view = (RecyclerView) findViewById(R.id.chat_view);
chat_view.setVerticalScrollBarEnabled(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
chat_view.setLayoutManager(layoutManager);
adapter = newAdapter();
chat_view.setAdapter(adapter);
message_text = (EditText) findViewById(R.id.message_text);
message_text.setEnabled(appUtils.isSignedIn());
findViewById(R.id.send_button).setEnabled(appUtils.isSignedIn());
}
So, there we have it, I have no idea what the problem could be at this point. I am using the most recent Firestore UI dependency as well.
It seems that you have done everything necessary..using FirestoreRecycleroptions and inflating the layout in onCreateViewHolder.
For FirestoreRecyclerAdapter to be able to have the data on the activity, then you need to listen to any changes in onStart() which is after onCreate(). Also
in onStop you can stop listening.
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
This line of codes gives me red lines of error. i dont know what i did wrong. one thing i nottice when i type in "new FirebaseRecyclerAdapter" it gives me override methods of 2 insteads of 1 which is onPopulateViewHolder is missing from what ive seen in a video tutorial of TVAC on Youtube.
here is the code:
public class ViewListTutor extends AppCompatActivity {
private RecyclerView mListTutor;
private DatabaseReference mlistDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_list_tutor);
mlistDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child("Tutors");
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mListTutor = (RecyclerView) findViewById(R.id.tutor_list);
mListTutor.setHasFixedSize(true);
mListTutor.setLayoutManager(new LinearLayoutManager(this));
}
#Override
protected void onStart() {
super.onStart();
FirebaseRecyclerAdapter<ListTutorItem, TutorViewHolder> FirebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ListTutorItem, TutorViewHolder>(
ListTutorItem.class,
R.layout.tutor_row,
TutorViewHolder.class,
mlistDatabase
) {
#Override
protected void onBindViewHolder(TutorViewHolder holder, int position, ListTutorItem model) {
}
#Override
public TutorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
};
}
image:
my dependency for UI Firebase Database:
compile 'com.firebaseui:firebase-ui-database:0.4.0'
I have used Firebase RecyclerViewAdapter extensively in my app but since the below code doesn't fire populateViewHolder without any data to load in the first place, I can't show the load complete message for the initial load
RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, mRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
};
recycler.setAdapter(mAdapter);
What you're describing is covered by this feature: Handle empty state for recycleview. You can handle this by implementing onDataChanged() in your adapter. A snippet from the sample app of FirebaseUI:
#Override
protected void onDataChanged() {
// if there are no chat messages, show a view that invites the user to add a message
mEmptyListView.setVisibility(
mRecyclerViewAdapter.getItemCount() == 0 ? View.VISIBLE : View.INVISIBLE
);
}
if(chatMessage.getName().equals("")){ //null value }else{
//execute code }
Override onDataChanged() and check in it
mAdapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, mRef) {
#Override
public void populateViewHolder(ChatHolder chatMessageViewHolder, Chat chatMessage, int position) {
chatMessageViewHolder.setName(chatMessage.getName());
chatMessageViewHolder.setText(chatMessage.getText());
}
#Override
protected void onDataChanged() {
// do your tests here
}
};