Problem deleting entry from Recycler View - java

This issue is driving me crazy. I've tried 20 different things by now. So let's see if someone here can help me.
I am making a ToDo list APP using RecyclerView that stores the data in Firebase.
The app has a TasksActivity where all the tasks appear in the RecyclerView. I have a button that goes to a Task Creation dialogue. And I can create tasks, they appear then in the RecyclerView (Tasks Activity) and are updated in the firebase with no issue. I can close the APP and come back later and everything works well, all the entries appear in the app again when I load it. I can also swipe to delete an entry, and the entry also gets eliminated from the Database in firebase.
The problem, is when I create a TASK and without closing the app, I try to delete the task that I just created. It doesn't allow me to do that. When I create a new task, and instantly delete it before closing the app, it appears again. But If I then close the app, and load it again, that entry can be deleted normally, but if I am in the same session in which I created the entry there's no way I can delete it.
I was using some Log.d arguments to see how it changes. I think for various reasons that the problem is OnDataChange(). But so far I haven't been able to come to the root of the issue. This is the TaskActivity class, and after this I will paste the TasksCreation (I don't think pasting the Adapter is necessary).
public class TasksActivity extends AppCompatActivity {
DatabaseReference reference;
RecyclerView myTasks;
ArrayList<TaskItems> myTasksList;
TasksAdapter tasksAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasks);
myTasks = findViewById(R.id.my_tasks); // RecyclerView that I defined as part of the layout. This is the id of it
myTasks.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
myTasksList = new ArrayList<>();
Button openCreateTask = findViewById(R.id.openCreateTask);
tasksAdapter = new TasksAdapter(this,myTasksList);
myTasks.setAdapter(tasksAdapter);
new ItemTouchHelper(itemTouchHelper).attachToRecyclerView(myTasks);
openCreateTask.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent_task = new Intent(getApplicationContext(), TasksCreation.class);
startActivity(intent_task);
}
});
reference = FirebaseDatabase.getInstance().getReference().child("MotApp"); // Name of the App in the database .child("MotApp")
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) { // It gets the info from the database
Log.d("data Changed called", "onDataChange: is called");
Log.d("whatever", "onDataChange BEGIN Array of myTasksList size is "+myTasksList.size());
myTasksList.clear(); // Added later to avoid duplication
for(DataSnapshot elements: dataSnapshot.getChildren()){
TaskItems p = elements.getValue(TaskItems.class);
myTasksList.add(p);
}
tasksAdapter.notifyDataSetChanged(); // If this is put outside of onDataChange, it displays a blank list.
Log.d("whatever", "onDataChange END Array of myTasksList size is "+myTasksList.size());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "No data", Toast.LENGTH_SHORT).show();
}
});
}
ItemTouchHelper.SimpleCallback itemTouchHelper = new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
Log.d("ARRAY SIZE", "onSwiped BEGIN Array of myTasksList size is "+myTasksList.size());
String key = myTasksList.get(position).getKey();
reference= FirebaseDatabase.getInstance().getReference().child("MotApp").child(key);
Toast.makeText(getApplicationContext(),"This is key "+key,Toast.LENGTH_LONG).show();
reference.removeValue();
myTasksList.remove(position);
tasksAdapter.notifyItemRemoved(position);
Log.d("ARRAY SIZE", "onSwiped END Array of myTasksList size is "+myTasksList.size());
}
};
}
And this is for TasksCreation Activity:
public class TasksCreation extends AppCompatActivity {
DatabaseReference referenceCreation;
ArrayList<String> list;
EditText taskName;
EditText taskDescr;
Button selectDates;
TextView taskDate;
Button createTask;
Button cancel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasks_creation);
taskName = findViewById(R.id.et_TaskName);
taskDescr = findViewById(R.id.et_TaskDescr);
selectDates = findViewById(R.id.selectDates);
taskDate= findViewById(R.id.tv_Dates);
createTask = findViewById(R.id.createTask);
cancel = findViewById(R.id.cancelButton);
createTask.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!TextUtils.isEmpty(taskName.getText()) && !TextUtils.isEmpty(taskDate.getText())) {
referenceCreation = FirebaseDatabase.getInstance().getReference().child("MotApp").push(); //saves it with custom key created by Firebase
final String key = referenceCreation.getKey();
referenceCreation.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
dataSnapshot.getRef().child("key").setValue(key);
dataSnapshot.getRef().child("taskTitle").setValue(taskName.getText().toString());
dataSnapshot.getRef().child("taskDescription").setValue(taskDescr.getText().toString());
dataSnapshot.getRef().child("taskDate").setValue(taskDate.getText().toString());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Intent intent = new Intent(getApplicationContext(), TasksActivity.class);
startActivity(intent);
} else{
Toast.makeText(getApplicationContext(), "You haven't filled all the fields", Toast.LENGTH_SHORT).show();
}
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), TasksActivity.class);
startActivity(intent);
}
});
selectDates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createAlertDialogue();
}
});
}
private void createAlertDialogue(){
list = new ArrayList<String>();
AlertDialog.Builder builder = new AlertDialog.Builder(this,R.style.MyDialogTheme);
builder.setTitle("Select days");
builder.setMultiChoiceItems(R.array.Days, null, new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
String arr[] = getResources().getStringArray(R.array.Days);
if(isChecked){
list.add(arr[which]);
}else if(list.contains(arr[which])){
list.remove(arr[which]);
}
}
});
builder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
String data = "";
#Override
public void onClick(DialogInterface dialog, int which) {
for(String elements: list){
elements = elements.substring(0,3);
data= elements+" "+data;
}
taskDate.setText(data);
}
});
builder.create();
builder.show();
}
}
I really appreciate any light to the issue.
Thanks a lot
P:S: This is the code for the TaskAdapter (Ignore the dayoftheweek part is just for a part of the code that I commented )
public class TasksAdapter extends RecyclerView.Adapter<TasksAdapter.MyViewHolder> { // V 1.3 added OnClickListener
Context context;
ArrayList<TaskItems> tasks;
DatabaseReference reference;
SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
Date d = new Date();
final String dayOfTheWeek = sdf.format(d).substring(0,3);
public TasksAdapter(Context context, ArrayList<TaskItems> tasks) {
this.context = context;
this.tasks = tasks;
}
public class MyViewHolder extends RecyclerView.ViewHolder { // V1.3 Added implements View.OnClickListener
TextView taskTitle;
TextView taskDate;
TextView taskDescription;
CheckBox taskCheckBox;
ConstraintLayout constraintLayout; // Added to change background of each RecyclerView item.
public MyViewHolder(#NonNull View itemView) {
super(itemView);
taskTitle = itemView.findViewById(R.id.taskTitle);
taskDate = itemView.findViewById(R.id.taskDate);
taskDescription = itemView.findViewById(R.id.taskDescription);
taskCheckBox = itemView.findViewById(R.id.taskCheckBox);
constraintLayout = (ConstraintLayout) itemView.findViewById(R.id.item_task_layout);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
// if(pos != RecyclerView.NO_POSITION){//Checks if item still exists
TaskItems clickedDataItem = tasks.get(pos);
Toast.makeText(v.getContext(), "You clicked " + clickedDataItem.getTaskTitle(), Toast.LENGTH_SHORT).show();
// }
}
});
}
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) { // standard code for onCreateViewHolder
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_task,parent,false));
}
#Override
public void onBindViewHolder(final #NonNull MyViewHolder holder, final int position) { // This method is called once for each item on the list.
holder.taskTitle.setText(tasks.get(position).getTaskTitle());
holder.taskDescription.setText(tasks.get(position).getTaskDescription());
holder.taskDate.setText(tasks.get(position).getTaskDate());
holder.taskCheckBox.setChecked(tasks.get(position).isChecked());
holder.taskCheckBox.setTag(tasks.get(position).getKey());
holder.taskCheckBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
String post = (String) holder.taskCheckBox.getTag();
Toast.makeText(context,"This is checkbox number: "+post,Toast.LENGTH_SHORT).show(); // Working Well. //change for new logic
reference = database.getReference("MotApp").child(post);
boolean checkboxStatus = holder.taskCheckBox.isChecked();
Log.d("Checked", "onClick: The taskcheckbox checked is "+holder.taskCheckBox.isChecked());
TaskItems value = new TaskItems(tasks.get(position).getKey(),tasks.get(position).getTaskTitle(), tasks.get(position).getTaskDate(),tasks.get(position).getTaskDescription(),checkboxStatus);
reference.setValue(value);
Toast.makeText(context,"This is a checkbox belonging to item "+tasks.get(position).getTaskTitle(),Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() { //tells the adapter the size . if it's zero then it won't create anything
return tasks.size();
}
}

You need to rebuild the RecyclerView data in your TasksActivity when you return back from the TasksCreation; that is because the onCreate() callback of the TasksActivity is called only when you open your app; and that is why the deletion works only when you close your app and reopen it.
And onCreate() is not called when you back from the the TasksCreate, because when you transfer from TasksActivity to TasksCreation, the TasksActivity is not destroyed, but just stopped, and therefore when you come back to TasksActivity it will start, and resumed; so transfer your code on the onCreate() to onResume() in order to allow the list to be updated with the recent changes.
So change your TasksActivity to the below
public class TasksActivity extends AppCompatActivity {
DatabaseReference reference;
RecyclerView myTasks;
ArrayList<TaskItems> myTasksList;
TasksAdapter tasksAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasks);
}
#Override
protected void onResume() {
super.onResume();
myTasks = findViewById(R.id.my_tasks); // RecyclerView that I defined as part of the layout. This is the id of it
myTasks.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
myTasksList = new ArrayList<>();
Button openCreateTask = findViewById(R.id.openCreateTask);
tasksAdapter = new TasksAdapter(this,myTasksList);
myTasks.setAdapter(tasksAdapter);
new ItemTouchHelper(itemTouchHelper).attachToRecyclerView(myTasks);
openCreateTask.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent_task = new Intent(getApplicationContext(), TasksCreation.class);
startActivity(intent_task);
}
});
reference = FirebaseDatabase.getInstance().getReference().child("MotApp"); // Name of the App in the database .child("MotApp")
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) { // It gets the info from the database
Log.d("data Changed called", "onDataChange: is called");
Log.d("whatever", "onDataChange BEGIN Array of myTasksList size is "+myTasksList.size());
myTasksList.clear(); // Added later to avoid duplication
for(DataSnapshot elements: dataSnapshot.getChildren()){
TaskItems p = elements.getValue(TaskItems.class);
myTasksList.add(p);
}
tasksAdapter.notifyDataSetChanged(); // If this is put outside of onDataChange, it displays a blank list.
Log.d("whatever", "onDataChange END Array of myTasksList size is "+myTasksList.size());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "No data", Toast.LENGTH_SHORT).show();
}
});
}
ItemTouchHelper.SimpleCallback itemTouchHelper = new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
int position = viewHolder.getAdapterPosition();
Log.d("ARRAY SIZE", "onSwiped BEGIN Array of myTasksList size is "+myTasksList.size());
String key = myTasksList.get(position).getKey();
reference= FirebaseDatabase.getInstance().getReference().child("MotApp").child(key);
Toast.makeText(getApplicationContext(),"This is key "+key,Toast.LENGTH_LONG).show();
reference.removeValue();
myTasksList.remove(position);
tasksAdapter.notifyItemRemoved(position);
Log.d("ARRAY SIZE", "onSwiped END Array of myTasksList size is "+myTasksList.size());
}
};
}

I finally found how to solve this.
First I changed all addValueEventListener with addListenerforSingleValueEvent in TaskActivity and TaskCreation. With addValueEventListener I realized that it was making several loops everytime a new task was created which caused all kind of problems.
And I also changed the way the startIntent was set up in TaskCreation. I had set it up initially after the Listener block. But the asynchronous nature of onDataChange was making that everytime I loaded the intent the updated information wasn't set up with the new task that was just added.
By putting it inside the onDataChange it was solved. I have made several tests and now it's working flawlessly.
I wasted many days trying to solve this. But I learned a lot of lessons in the process. So I guess they weren't wasted days :) .
Thanks to all who chipped in to help me with this issue.

Related

Is there a way to prevent the skipping of layout for the recyclerview?

Basically the app it's just a simple to do list, but when I add new task to do, it appears on firebase, but not on my app, giving the error
"E/RecyclerView: No adapter attached; skipping layout".
I tried to fix it following the answers here on stackoverflow but none of them helped me, probably I was wrong to adapt the adjustments to my code. I'm just learning and this is my first project, I was following a tutorial to do it.
Anyway, this is the MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonadd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
Intent a = new Intent(MainActivity.this, AggiungiPiattoAttivity.class);
startActivity(a);
}
});
//working with data
ourdoes = findViewById(R.id.ourdoes);
ourdoes.setLayoutManager(new LinearLayoutManager(this));
list = new ArrayList<MyDoes>();
//get data from firebase
reference = FirebaseDatabase.getInstance(URL).getReference().child("AppLista");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//set code to retrive data and replace layout
for (DataSnapshot dataSnapshot1: dataSnapshot.getChildren())
{
MyDoes p = dataSnapshot1.getValue(MyDoes.class);
list.add(p);
}
doesAdapter = new DoesAdapter(MainActivity.this, list);
ourdoes.setAdapter(doesAdapter);
doesAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
//set code to show an error
Toast.makeText(getApplicationContext(), "No Data", Toast.LENGTH_SHORT).show();
}
});
}
This is the class where I add a new to do task:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aggiungi_piatto_attivity);
buttonaddnewpiatto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//insert data to database
reference = FirebaseDatabase.getInstance(URL).getReference().child("BoxDoese").child("Does" + doesNum);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
dataSnapshot.getRef().child("titledoes").setValue(addnamenewpiattosetted.getText().toString());
dataSnapshot.getRef().child("descdoes").setValue(adddescnewpiattosetted.getText().toString());
dataSnapshot.getRef().child("qualcosaalpostodiunimmagine").setValue(addrecipenewpiattosetted.getText().toString());
Intent a = new Intent( AggiungiPiattoAttivity.this, MainActivity.class);
startActivity(a);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
});
This is my adapter class:
public class DoesAdapter extends RecyclerView.Adapter<DoesAdapter.MyViewHolder> {
Context context;
ArrayList<MyDoes> myDoes;
public DoesAdapter(){
}
public DoesAdapter(Context c, ArrayList<MyDoes> p ){
context = c;
myDoes=p;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_does, viewGroup, false));
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.titledoes.setText(myDoes.get(i).getTitledoes());
myViewHolder.qualcosaalpostodiunimmagine.setText(myDoes.get(i).getQualcosaalpostodiunimmagine());
myViewHolder.descdoes.setText(myDoes.get(i).getDescdoes());
}
#Override
public int getItemCount() {
return myDoes.size();
}
class MyViewHolder extends RecyclerView.ViewHolder{
TextView titledoes, descdoes, qualcosaalpostodiunimmagine;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
titledoes = (TextView) itemView.findViewById(R.id.titledoes);
qualcosaalpostodiunimmagine = (TextView) itemView.findViewById(R.id.qualcosaalpostodiunimmagine);
descdoes = (TextView) itemView.findViewById(R.id.descdoes);
}
}
}
I also have other classes but to not put too much code I avoid to put them, they should not be relevant.
Create an empty adapter the same time you set LayoutManager for the RecyclerView: Save it as field of your class:
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
doesAdapter = new DoesAdapter(MainActivity.this, list);
recyclerView.setAdapter(DoesAdapter);
When data is ready, populate the adapter and notify:
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
/// origin code here
for (DataSnapshot dataSnapshot1: dataSnapshot.getChildren())
{
MyDoes p = dataSnapshot1.getValue(MyDoes.class);
list.add(p);
}
// reset data in adapter and not re-creating adapter:
doesAdapter.setItems(list);
doesAdapter.notifyDataSetChanged();
// instead of doesAdapter = new DoesAdapter(MainActivity.this, list);
recyclerView.setAdapter(DoesAdapter);
}
Source: https://stackoverflow.com/a/58251986/12596713

RecyclerView updates view upon object deletion except for last object

In my app, I have an activity that displays an ArrayList of students in a RecyclerView. The students are stored in Firebase Realtime Database. The user can add or delete students. When a user deletes a student, the RecyclerView updates and shows the remaining students.
But I have a problem. For example, say I had 5 students. I want to delete all 5 so I delete them one by one. 4 of the students delete correctly and the RecyclerView updates and reflects this. It's only when I delete the last student the RecyclerView doesn't update and the student CardView stays there. I get a toast message confirming the student's deletion and I can see they have been deleted in the database. If I navigate back to the dashboard and go back into the student list, the CardView then disappears. Strange.
I've tried calling onStart again after each deletion but this hasn't helped. Any ideas?
My activity:
public class StudentListActivity extends AppCompatActivity {
//firebase auth
private FirebaseAuth mAuth;
//public variables
public String currentUserAccount;
public String teacherAccountNav = "Teacher";
public String currentUserId;
//recyclerView variables
DatabaseReference ref;
ArrayList<Student> list;
RecyclerView recyclerView;
SearchView searchView;
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_student_list);
//get current user
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
//assert current user is not null and get current users id
assert user != null;
currentUserId = user.getUid();
//getting firebase reference of current users students
ref = FirebaseDatabase.getInstance().getReference().child("students").child(currentUserId);
//initialise views
recyclerView = findViewById(R.id.rv);
recyclerView.setHasFixedSize(true);
searchView = findViewById(R.id.searchView);
}
#Override
protected void onStart() {
super.onStart();
if(ref != null){
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//add students from firebase to an array list
if(dataSnapshot.exists()){
list = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()){
list.add(ds.getValue(Student.class));
}
//sort by name
Collections.sort(list, Student.myName);
//make recycler view
recyclerView.setLayoutManager(new LinearLayoutManager(StudentListActivity.this));
StudentAdapterClass studentAdapterClass = new StudentAdapterClass(list);
recyclerView.setAdapter(studentAdapterClass);
//click listeners for buttons
studentAdapterClass.setOnItemClickListener(new StudentAdapterClass.OnItemClickListener() {
#Override
public void onUpdateClick(int position) {
//handle update click in here
Student student = list.get(position);
//show update dialog here
showUpdateDialog(student.getStudentId(), student.getStudentName(), student.getStudentEmail());
}
#Override
public void onDeleteClick(int position){
//handle delete click in here
Student student = list.get(position);
//show delete dialog here
showDeleteDialog(student.getStudentId());
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(StudentListActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}//if
}
//dialog box for deleting student
private void showDeleteDialog(final String studentId){
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
//dialog XML
final View dialogView = inflater.inflate(R.layout.delete_student_dialog, null);
dialogBuilder.setView(dialogView);
final ImageButton buttonNo = dialogView.findViewById(R.id.imageButtonNo);
final ImageButton buttonYes = dialogView.findViewById(R.id.imageButtonYes);
final AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
buttonNo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
buttonYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deleteStudent(studentId);
alertDialog.dismiss();
}
});
}
//delete student method
private void deleteStudent(String id){
//get current user
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
//assert current user is not null and get current users id
assert user != null;
currentUserId = user.getUid();
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("students").child(currentUserId).child(id);
databaseReference.removeValue();
Toast.makeText(this, "Student Deleted", Toast.LENGTH_LONG).show();
//clear and get new list
onStart();
}
My adapter:
public class StudentAdapterClass extends RecyclerView.Adapter<StudentAdapterClass.MyViewHolder> {
private ArrayList<Student> list;
private OnItemClickListener mListener;
public interface OnItemClickListener{
//click method for update button
void onUpdateClick(int position);
//click method for delete button
void onDeleteClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
public StudentAdapterClass(ArrayList<Student> list){
this.list = list;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_holder, viewGroup, false);
return new MyViewHolder(view, mListener);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder myViewHolder, int i) {
myViewHolder.name.setText(list.get(i).getStudentName());
myViewHolder.email.setText(list.get(i).getStudentEmail());
}
#Override
public int getItemCount() {
return list.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
TextView name, email;
ImageButton update, delete;
MyViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
name = itemView.findViewById(R.id.studentName);
email = itemView.findViewById(R.id.studentEmail);
update = itemView.findViewById(R.id.updateButton);
delete = itemView.findViewById(R.id.deleteButton);
//update click listener
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onUpdateClick(position);
}
}
}
});
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION){
listener.onDeleteClick(position);
}
}
}
});
}
}
Every time RecyclerView data changed, you have to call the adapter method notifyDataSetChanged(), otherwise, RecyclerView cannot refresh correctly.
You can call it inside deleteStudent() method like this.
recyclerView.getAdapter().notifyDataSetChanged()

I'm looking for a solution, to remove the item on the right position in the Adapter

I got stuck today with coding because I was trying to remove a child on the Firebase Realtime Database and at the same time to remove the item from the ArrayList and the wrong view has been removed from the RecyclerView.
Also, the same thing works well on another fragment and I have no idea why.
Here is my method for populating the Recyclerview in the Fragment:
private void populateRV(ArrayList<Task> myTasksArrayList) {
MyTasksAdapter myTasksAdapter = new MyTasksAdapter(myTasksArrayList, getActivity());
myTasksAdapter.notifyDataSetChanged();
myTasksRV.setAdapter(myTasksAdapter);
myTasksRV.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setStackFromEnd(true);
linearLayoutManager.setReverseLayout(true);
myTasksRV.setLayoutManager(linearLayoutManager);
// query.removeEventListener(this);
}
This method above is called in a ValueEventListener, to get the data and to add it to the ArrayList.
And here is the onBindViewHolder:
#Override
public void onBindViewHolder(#NonNull final MyTasksViewHolder holder, final int position) {
title = myTasksArrayList.get(position).getTitle();
category = myTasksArrayList.get(position).getCategory();
description = myTasksArrayList.get(position).getDescription();
helperName = myTasksArrayList.get(position).getHelperName();
timeStamp = myTasksArrayList.get(position).getTimestamp();
holder.taskTitle.setText(title);
holder.taskCategory.setText(category);
holder.taskDescription.setText(description);
holder.deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myTasksArrayList.remove(holder.getAdapterPosition());
notifyItemRemoved(holder.getAdapterPosition());
removeChildFromDatabase();
}
});
PROBLEM 1:
When I press the deleteBtn the wrong item will be removed from the RecyclerView.
PROBLEM 2:
If I remove the ValueEnventListener: // query.removeEventListener(this); will remove the right item BUT after if I add an item to the list will not show, because the ValueEnventListener will remain removed.
You are dealing with a Class of object that sends values from Firebase Real-time and stores these values in the ArrayList of the Class of object type.
In my opinion, it is not necessary to delete every element of RecyclerView. modified in Firebase at the same time it is modified in the adapter.
PROBLEM 1:
#Override
public void onBindViewHolder(#NonNull final MyTasksViewHolder holder, final int position) {
title = myTasksArrayList.get(position).getTitle();
category = myTasksArrayList.get(position).getCategory();
description = myTasksArrayList.get(position).getDescription();
helperName = myTasksArrayList.get(position).getHelperName();
timeStamp = myTasksArrayList.get(position).getTimestamp();
holder.taskTitle.setText(title);
holder.taskCategory.setText(category);
holder.taskDescription.setText(description);
holder.deleteBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DatabaseReference db_node = FirebaseDatabase.getInstance().getReference("//YUOR ROOT IN DATABASE");
db_node.removeValue();
notifyDataSetChanged(); //It reloads the adapter again
}
});
PROBLEM 2:
In this problem you have to recover the data and when the application stops to avoid any other problem you should delete removeEventListener.
#Override
protected void onStart() {
super.onStart();
valueEventLis = Ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
list = new ArrayList<>();
for (DataSnapshot snapshot : dataSnapshot.getChildren())
//... etc list.add(snapshot.getValue(etc.class));
populateRV(list);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
And:
#Override
protected void onPause() {
super.onPause();
if (valueEventLis != null)
Ref.removeEventListener(valueEventLis);
}

Android to Firebase reduce/compress/resize the image size before uploading it [duplicate]

I am using RecyclerView in my application for the professor to see the students list where there will be photos and other details and delete options. Everything I tried to do carefully. But there is a problem that photo from firebase is not loading into the RecyclerView. Sometimes it loads one or two photos then it stops loading photo. I was observing the Run option on android Studio while my app is loading. Then I found something like...
W/art: Throwing OutOfMemoryError "Failed to allocate a 71663628 byte allocation with 4188416 free bytes and 46MB until OOM"
V/FA: Inactivity, disconnecting from the service
Why this problem happening to me, I really didn't get yet. Please, help me to get life from this problem.
After looking for a lot, I tried some steps where said to invalidate caches/ restart. But that didn't work for me.
Here is my main activity for RecyclerView:
public class HRequestedStudents extends AppCompatActivity {
DatabaseReference databaseReference;
ProgressDialog progressDialog;
List<RegisteredStudent> list = new ArrayList<>();
RecyclerView recyclerView;
RecyclerView.Adapter adapter ;
RequestedStudents madapter;
RegisteredStudent registeredStudent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hrequested_students);
recyclerView = (RecyclerView) findViewById(R.id.recycleView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(HRequestedStudents.this));
progressDialog = new ProgressDialog(HRequestedStudents.this);
progressDialog.setMessage("Loading Data...");
progressDialog.show();
databaseReference = FirebaseDatabase.getInstance().getReference("RegisteredStudent");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
list.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
registeredStudent = dataSnapshot.getValue(RegisteredStudent.class);
list.add(registeredStudent);
}
adapter = new RequestedStudents(HRequestedStudents.this, list);
recyclerView.setAdapter(adapter);
progressDialog.dismiss();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
progressDialog.dismiss();
}
});
}
}
Here is my adapter activity
public class RequestedStudents extends RecyclerView.Adapter<RequestedStudents.RecyclerViewHolder> {
private Context mContext;
ProgressDialog progressDialog;
List<RegisteredStudent> requestedStudents;
FirebaseStorage mFirebaseStorage = getInstance();
DatabaseReference mRef = FirebaseDatabase.getInstance().getReference("RegisteredStudent");
public RequestedStudents(Context context, List<RegisteredStudent> list) {
mContext=context;
requestedStudents = list;
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.hrstudentlistitems, parent, false);
return new RecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
RegisteredStudent currentStudentDetails = requestedStudents.get(position);
holder.name.setText("Name: "+currentStudentDetails.getRegeName());
holder.room.setText("Room: "+currentStudentDetails.getRegeRoom());
holder.id.setText("ID: "+currentStudentDetails.getRegeID());
holder.batch.setText("Batch: "+currentStudentDetails.getRegeBatch());
holder.dept.setText("Department: "+currentStudentDetails.getRegeDept());
holder.email = currentStudentDetails.getRegeEmail();
holder.nam = currentStudentDetails.getRegeName();
holder.rum = currentStudentDetails.getRegeRoom();
holder.mobile = currentStudentDetails.getRegeMobile();
holder.pass = currentStudentDetails.getRegePass();
holder.iD = currentStudentDetails.getRegeID();
holder.Batch = currentStudentDetails.getRegeID();
holder.Dept = currentStudentDetails.getRegeDept();
holder.imageUri = currentStudentDetails.getImageUri();
Picasso.get().load(currentStudentDetails.getImageUri()).into(holder.profile_photo);
}
#Override
public int getItemCount() {
return requestedStudents.size();
}
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
public TextView name, id, room, batch, dept;
public String email, mobile, imageUri, pass, iD, nam, rum, uId, Batch, Dept;
public CircleImageView profile_photo;
public Button remove, accept;
public RecyclerViewHolder(View item) {
super(item);
name = item.findViewById(R.id.name);
room = item.findViewById(R.id.room);
id = item.findViewById(R.id.id);
batch = item.findViewById(R.id.batch);
dept = item.findViewById(R.id.dept);
profile_photo = item.findViewById(R.id.profile_photo);
remove = item.findViewById(R.id.remove);
accept = item.findViewById(R.id.accept);
item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialog = new ProgressDialog(mContext);
progressDialog.setMessage("Please Wait...");
progressDialog.show();
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.student_bistarito, null);
CircleImageView imagebi = view.findViewById(R.id.imagebi);
TextView nambi = view.findViewById(R.id.nambi);
TextView rumbi = view.findViewById(R.id.rumbi);
Button call = view.findViewById(R.id.call);
Button cancel = view.findViewById(R.id.cancel);
final AlertDialog alertDialog = new AlertDialog.Builder(mContext).create();
nambi.setText("Name: " + nam);
rumbi.setText("Room: " + rum);
Picasso.get().load(imageUri).into(imagebi);
progressDialog.dismiss();
uId = FirebaseAuth.getInstance().getUid();
call.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_CALL);
i.setData(Uri.parse("tel:" + mobile));
if (ContextCompat.checkSelfPermission(mContext, CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
mContext.startActivity(i);
} else {
Toast.makeText(mContext, "Go to settings and allow call permission", Toast.LENGTH_LONG).show();
}
alertDialog.dismiss();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Toast.makeText(mContext, "Shubho", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_LONG).show();
}
alertDialog.dismiss();
}
});
alertDialog.setView(view);
alertDialog.show();
alertDialog.getWindow().setBackgroundDrawable(null);
}
});
profile_photo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View vi = inflater.inflate(R.layout.activity_photo, null);
ImageView photo = vi.findViewById(R.id.image);
Button close = vi.findViewById(R.id.close);
final AlertDialog ad = new AlertDialog.Builder(mContext).create();
Picasso.get().load(imageUri).into(photo);
close.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ad.dismiss();
}
});
ad.setView(vi);
ad.show();
ad.getWindow().setBackgroundDrawable(null);
}
});
accept.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Delete");
builder.setMessage("Are you sure to remove this student?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
try {
Query query = mRef.orderByChild("email").equalTo(email);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
ds.getRef().removeValue();
}
Toast.makeText(mContext, "Removed Successfully!", Toast.LENGTH_SHORT).show();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(mContext, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
StorageReference mPictureReferance = getInstance().getReferenceFromUrl(imageUri);
mPictureReferance.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(mContext, "Removed Successfully!", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
});
}
}
}
I want to load all images into the RecyclerView without getting the error line "Inactivity, Disconnecting from the service". How can I solve this?
The error you showed upside means that the image size is very large.
What you can do is
While uploading photos to Firebase you can compress the photo size and then upload it. So that when your android app gets photo from Firebase then the image size will be less and it can allocate easily.
You can use refer to https://developer.android.com/topic/performance/graphics/load-bitmap to load heavy or large images into android efficiently.
First will be considered as the way everyone do. As your Firebase storage will be used less and users can download your images easily in App without any Lag or memory problem.
The best solution I can think of would be to use the Resize Images Extension:
Resizes images uploaded to Cloud Storage to a specified size, and stores both the original and resized images.
Here is the Github repo.

How to implement OnClick item using firebase search query result item

I've created a firebase search query and it works perfectly.But now I can't seem to figure out how to do the onlick and get item position. Below is my firebase search activity:
mUserDatabase=FirebaseDatabase.getInstance().getReference("Users").child("UserProfile";
mSearchField = findViewById(R.id.search_field);
mSearchBtn = findViewById(R.id.search_btn);
mResultList = findViewById(R.id.result_list);
mResultList.setHasFixedSize(true);
mResultList.setLayoutManager(new LinearLayoutManager(this));
mSearchBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String searchText = mSearchField.getText().toString();
firebaseUserSearch(searchText);
}
});
}
private void firebaseUserSearch(String searchText) {
Toast.makeText(SearchActivity.this, "Searching......", Toast.LENGTH_LONG).show();
Query firebaseSearchQuery = mUserDatabase.orderByChild("profession").startAt(searchText).endAt(searchText + "\uf8ff");
FirebaseRecyclerAdapter<Users, UsersViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Users, UsersViewHolder>(
Users.class,
R.layout.search_list_layout,
UsersViewHolder.class,
firebaseSearchQuery
) {
#Override
protected void populateViewHolder(UsersViewHolder viewHolder, Users model, int position) {
viewHolder.setDetails(getApplicationContext(), model.getUsername(), model.getSummary(), model.getImageurl());
}
};
mResultList.setAdapter(firebaseRecyclerAdapter);
}
public static class UsersViewHolder extends RecyclerView.ViewHolder {
View mView;
private TextView user_name;
private TextView user_summary;
private ImageView user_image;
public UsersViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setDetails(Context ctx, String userName,String userSummary,String userImage){
user_name = mView.findViewById(R.id.name_text);
user_summary = mView.findViewById(R.id.summary_text);
user_image = mView.findViewById(R.id.profile_image);
user_name.setText(userName);
user_summary.setText(userSummary);
Glide.with(ctx).load(userImage).into(user_image);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
Snackbar.make(v, "Hello,How may i help you", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
});
}
How do i go about displaying the content in a details activity when a single item from the search result is clicked.
Based on Parag Pawar's suggestion, I tried the following, but it's not working>
#Override
protected void populateViewHolder(UsersViewHolder viewHolder, Users model, int position) {
viewHolder.setDetails(getApplicationContext(), model.getUsername(), model.getSummary(), model.getImageurl());
final String each_key = getRef(position).getKey();
}
};
Then in my UserViewHolder i initialized the onclick:
mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent pDetail = new Intent(SearchActivity.this, ProfileDetail.class);
Users each_key = each_key.get(getAdapterPosition());
pDetail.putExtra(ProfileDetail.EXTRA_POSITION, each_key.getUserId());
startActivity(pDetail);
}
});
But I am getting the error variable each_key might not have been initialized
Fixed my mistake according top advice from Parag Pawar and implemented he onclick inside populateView`holder as follows:
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*Here use intent.putExtra() to send each_key on other activity and fetch data there*/
Toast.makeText(SearchActivity.this, "u clicked......" +position, Toast.LENGTH_LONG).show();
Intent each_key = new Intent(SearchActivity.this, ProfileDetail.class);
Users user = mResultList.get(position);
each_key.putExtra(ProfileDetail.EXTRA_POSITION, user.getUserId());
startActivity(each_key);
} });
but I am getting the error here:
Users user = mResultList.get(position);
Cannot resolve method 'get(int)'
mReultList is the name of my Recyclerview and I initialized it as follows:
private RecyclerView mResultList;
but I don't know if I'm doing this correctly. I know I am supposed to attach the results to an adapter, but I don't know how to do that. So I tried:
listItems = new ArrayList<>();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<UsersList>(listItems,this);
But this doesn't seem to work either
Updated Code
I created an array:
private List<UsersList> listItems;//UsersList is my modal class
Then added it to my onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
listItems = new ArrayList<>();
I then Implemented putExtra as follows using this array as follows:
Intent each_key = new Intent(TestSearch.this, ProfileDetail.class);
UsersList user = listItems.get(position);
//Here use intent.putExtra() to send each_key on other activity and fetch data there
Toast.makeText(TestSearch.this, "u clicked......" +position, Toast.LENGTH_LONG).show();
each_key.putExtra(ProfileDetail.EXTRA_POSITION, user.getUserId());
startActivity(each_key);
But getting this error when i click an item:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:411)
at com.ecard.ecard.search.TestSearch$2$1.onClick(TestSearch.java:94)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
To get key from each item, in populateViewholder do
Example :-
final String each_key = getRef(position).getKey();
To set Click Listeners on each item, in populateViewholder do
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*Here use intent.putExtra() to send each_key on other activity and fetch data there*/
} }); }
In the activity that contains your current
items that you want to click on:
Create a String to reference from in your populateVieHolder:
final String single_view = getRef(position).getKey();
Then attach an onclick to your ViewHolder:
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
And in your OnClick place your intents and putExtras:
#Override
public void onClick(View view) {
//give your intent a name to reference from("moreDetail" in this case)
Intent moreDetail = new Intent(SearchActivity.this,MoreDetail.class);
//attach the intent reference to access each item and key
moreDetail.putExtra(MoreDetail.EXTRA_POSITION,single_view);
startActivity(moreDetail);//Start the new activity
Then in your more details activity:
Add the ExtraPosition String
String single_view = getIntent().getExtras().getString(MoreDetail.EXTRA_POSITION);//get extra position reference previous view
From here on,you need to display your data from firebase
For accessing Single Values from Firebase
firebaseRef.child(single_view).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//For single items
// for example:String user_name = (String) dataSnapshot.child("username").getValue();
Or
For accessing Values attached to your adapter using a Listview
firebaseRef.child(single_view).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ListItem data = dataSnapshot.getValue(ListItem.class);
listItems.add(data);
adapter.notifyDataSetChanged();
//if you are accessing your data from a ListView
There are so many ways to do this.Another way to accomplish this is to create an interface.declare an onclick listener and contex in your recycler adapter:
OnItemClickListener callback;
private Context mContext;
Then implement an Onclick listener to your view holder
public static class UsersViewHolder extends RecyclerView.ViewHolder implements OnItemClickListener {
add an onclick to access a position,to your View Holder using callback:
#Override
public void onClick(View v) {
callback.onItemClick(getAdapterPosition());
}
Then create an interface:
public interface OnItemClickListener {
void onItemClick(int pos);
}
Based on your context:
In your more main activity:
#Override
public void onItemClick(int pos) {
Intent pDetail = new Intent(this.getContext(), ProfileDetail.class);//get the context
ListItem listItem = listItems.get(pos);//get the position
//Then your puEtxra here followed by start activity
startActivity(pDetail);
}
And finally call EXTRA_POSITION in your detail view followed by your datasnapshots.
You can find more details from the firebase documentation and firebase quick start samples on github:
GitHub
FirebaseDocs
I said both the things go in populateViewHolder()
You are getting not initialized error because you're using each_key in the Viewholder class.
Copy this
final String each_key = getRef(position).getKey();
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*Here use intent.putExtra() to send each_key on other activity and fetch data there*/
} }); }
and paste it in the populateViewHolder method

Categories

Resources