I have a mChildEventListener that queries for the first n items from Firebase Database and another mChildEventListener2 (triggered when the user scroll up and clicks on a Load More button) that queries for the next n items and adds them to the ChatMessagesList.
When the user clicks on the Load More button: the ChatMessagesList is updated and notifyDataSetChanged is called. The mMessageListView is updated but it scrolls down to the buttom every time. I explained this behavior because of the xml attribute: android:transcriptMode="alwaysScroll".
When I remove transcriptMode="alwaysScroll" and the user presses on the Load More button, the mMessageListView scrolls this time to the top.
None of these behaviors are wanted. I would like that when the user presses the button, the mMessageListView would maintain its' scrolling position. (for obvious reasons)
I tried calling notifyDataSetChanged from a new thread. No results.
I tried using listView.setSelectionFromTop(lastViewedPosition, topOffset); or using list.smoothScrollToPosition(); but none achieved a smooth experience that I would want.
How can I maintain the scrolling position after the mMessageListView is updated?
This is the code:
private ChildEventListener mChildEventListener;
private ChildEventListener mChildEventListener2;
List<ChatMessage> ChatMessages = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mMessageAdapter = new MessageAdapter(this, R.layout.item_message_sent, ChatMessages);
mMessageListView.setAdapter(mMessageAdapter);
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if(i == 0) {
current_last_key = dataSnapshot.getKey();
}
else {
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
mMessageAdapter.add(chatMessage);
}
i++;
}
...
};
Query messagesQuery = mDatabaseReference.child("chat_messages").
child(chatId).limitToLast(25);
messagesQuery.addChildEventListener(mChildEventListener);
...
}
#Override
public void onClick(View v) {
j = 0;
mChildEventListener2 = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if(!dataSnapshot.getKey().equals(current_last_key)) {
if (j == 0) {
current_last_key = dataSnapshot.getKey();
}
else {
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
ChatMessages.add(j- 1, chatMessage);
}
}
else
{
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
ChatMessages.add(0 , chatMessage);
loadMoreTextView.setVisibility(View.GONE);
}
mMessageAdapter.notifyDataSetChanged();
j++;
}
... };
Query query = mDatabaseReference.child("chat_messages").
child(chatId).orderByKey().endAt(current_last_key).limitToLast(10);
query.addChildEventListener(mChildEventListener2);
}
notifyDataSetChanged()
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
Try to see if "onCreate()" is called again when updating
FirebaseUI lib handles all that for you and simplifies your code.
BTW, you can use mAdapter.notifyItemInserted(ChatMessages.size() - 1); or mMessageAdapter.notifyItemRangeInserted(ChatMessages.size() - 1, ChatMessages.size() - 1 + numberOfItemsBeingInserted); and make the other required changes in order for this to work, instead of using mMessageAdapter.notifyDataSetChanged();
Related
I just fetch data & load it into recyclerView that can be set on adapter. It contains a button which is able to send data to Firebase.
When I press the button its color and text changes as per requirement
but whenever I reload it again the default button state gets loaded.
So I want that button should save its state once clicked and whenever I reload the same activity it should be in the saved state.
viewHolder.send_req.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final Integer taggedPosition = viewHolder.getAdapterPosition();
Log.d(TAG,"button click data:"+taggedPosition);
firebaseFirestore.collection("Users").document(u_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.getResult().exists()){
name = task.getResult().getString("name");
userID = task.getResult().getString("user_id");
firebaseFirestore.collection("Pets").whereEqualTo("name",name_data).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (final DocumentSnapshot documentSnapshot : task.getResult()){
docID = documentSnapshot.getId();
Log.d(TAG,"selected pet doc id:"+docID);
if (docID!= null){
final Map<String, Object> userMap = new HashMap<>();
final Map<String, Object> userMap1 = new HashMap<>();
userMap.put("doc_id",docID);
userMap.put("pet_id",pet_no);
userMap.put("sender_id",userID);
userMap.put("sender_name",name);
userMap.put("pet_name",name_data);
userMap.put("pet_profile",image_url);
userMap.put("timestamp",FieldValue.serverTimestamp());
//do not place request if data is already exist in document
firebaseFirestore.collection("Send_req").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
List<String> list = new ArrayList<>();
final Button send_req = (Button)v;
if (task.isSuccessful()){
for (DocumentSnapshot document : task.getResult()) {
list.add(document.getString("doc_id"));
list.add(document.getString("sender_id"));
}
if (!(list.contains(docID)&& list.contains(userID))){
send_req.setClickable(true);
Toast.makeText(context,"send request successfully",Toast.LENGTH_SHORT).show();
send_req.setText("Cancel Request");
send_req.setBackgroundColor(Color.RED);
String btnname =send_req.getText().toString();
String button_name = (String)userMap.put("btnName",btnname);
firebaseFirestore.collection("Send_req").add(userMap);
send_req.setClickable(false);
}
else {
if ((list.contains(docID)&& list.contains(userID))){
if(send_req.getText().toString().equals("Send Request") )
Toast.makeText(context,"you already send request",Toast.LENGTH_SHORT).show();
send_req.setText("Cancel Request");
send_req.setBackgroundColor(Color.RED);
send_req.setClickable(false);
notifyDataSetChanged();}
}
}
}
});
}
}
}
}
});
}
}
});
}
});
public class SomeClass {
public static boolean isFeatureSelected = false;
...
}
And you can always invoke it with SomeClass.isFeatureSelected.
If you already have the pojo of the response then you can define a variable in the pojo and change the value on button click on that position. As define by ChrisZ.
But if as you don't have pojo I will suggest you to create a List of Boolean size same as the recyclerView item size with false value. Once you click on the button make the list boolean to true at that position so you can know on which position you already clicked and change the UI with the bool value at that position.
Create a boolean variable such as:
boolean isClicked = false; and int pos = -1;
Then the first time you changed the button background change the boolean to true and pos = position;.
Then in the onBindViewHolder of your RecyclerView do this:
if(isClicked && position == pos){ // check the state of the button and the adapter position.
// change your background here
}
I'm making something like a social app.
I would like that if someone has already viewed something before, that the button in the view will change colors.
I have a method to check if someone has viewed this list before. It works in the clickListener, and will say "Already pressed."
I'm having a hard time figuring out how to change the color of the button, maybe on the onCreate method. I've tried passing it as an argument, but the color will change on the second time the list is pulled up...
This is how I call up my dialog and pass it the list ID.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View r = inflater.inflate(R.layout.list_view_dialog_layout, container, false);
checklistView = (UserlistView) r.findViewById(R.id.user_list);
checklistview.getList(getArguments().getString("list_id")); // Can be modified
return r;
}
in that function getList, I make my call to my database to get the info of the list.
public void getList(final String listID) {
// TODO fetch list information from params and fill fields
Event.requestEvent(listID, "AuthToken", new List.ListReceivedListener() {
#Override
public void onListReceived(lissts... lissteses) {
List lst = lissteses[0];
setInfo(lst);
LISTID = listID;
}
});
}
public void setInfo(List lst){
listTitleView.setText(lst.listName);
viewsCount.setText(Integer.toString(lst.views));
}
I have a checker function to see if the user has already clicked the "have viewed"
public static boolean viewed(String id, final String user){
DatabaseReference rootref = FirebaseDatabase.getInstance().getReference("views").child(id);
rootref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChild(user)){
result = true;
}
else{
result = false;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return result;
}
then, I wanted to call it in the getList() as such
if(viewed(lstID, curuser){
viewButton.setColorFilter(R.color.blue);
}
this doesn't work for the first time the view is created, and so, if the user has already clicked view, logs out and logs back in, and click view again, messing up the view count.
int flag=0;
button.setOnClickLitener(new OnClickListener()){
#Override
public void onClick(View arg0) {
flag++;
}
});
if(flag>0){
button.setBackgroundColor(getResources().getColor(R.color.yourColor));
}
Another solution is this.
button.setBackgroundColor(getResources().getColor(R.color.youCustomColor));
I'm fetching some data from FirebaseDatabase and then putting them into an array and then trying to show them in a List which is in a custom AlertDialog.
Here's the code:
query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");
uProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot != null) {
Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();
ArrayList<String> l = new ArrayList<String>();
l.add(newD.get("lol").substring(30));
String names[] = l.toArray(new String[0]);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this);
LayoutInflater inflater = getLayoutInflater();
View convertView = inflater.inflate(R.layout.dialog_list, null);
alertDialog.setView(convertView);
alertDialog.setTitle("title");
ListView lv = (ListView) convertView.findViewById(R.id.lv);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
lv.setAdapter(adapter);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
alertDialog.show();
} else {
Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show();
}
}
...
...
});
}
});
Here's the database structure:
app
-child
-anotherChild
-yetAnotherChild
-inaccessibleChild
-someChild: "value"
-lol: "value"
I can't use valueEventListener() here as I have no access to inaccessibleChild. The inaccessibleChild here is the uid of the other users who followed a particular user. How can I access there uid?
The problem is that data is getting fetched but instead of getting shown in a list in one AlertDialog, it is getting shown one-by-one in 3 separate AlertDialog.
What is going wrong here?
Please let me know.
Firebase transactions are asynchronous so your initial line to add the 3 children happens after you set your listener, therefore your callback is called 3 times. (making 3 dialogs).
Move this line outside of the on click:
query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");
Then when you add the below listener (inside the on click) it should be ok
query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Put limit when you are using valueEventListener or addChildEventListener. like this,
int limit = 100;
databaseRef.child("chats").limitToLast(limit).addValueEventListener(listener);
And always remove listener when you've done with your work related to firebase. like this,
databaseRef.child("chats").limitToLast(limit).removeEventListener(listener);
Thanks.
Create and show the AlertDialog before you call .addChildEventListener()
Then use inside addChildEventListener call notifyDatasetChanged() after you downloaded the appropriate data. Do not create the AlertDialog inside the addChildEventListener
You can use Firebase Queries to limit the data that is downloaded by a listener.
query.orderByChild("someChild").limitToLast(1).addChildEventListener(...
#Blundell has the insight of solving your problem. I just want to suggest you a similar approach with addValueEventListener.
The value event listener will fire once for the initial state of the
data, and then again every time the value of that data changes.
You need to move out the firebase query from onClick function. So your query might look like this..
// Declare the variable names as public
private String names[];
private void addFirebaseListener() {
ref = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");
ref. userRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();
ArrayList<String> l = new ArrayList<String>();
l.add(newD.get("lol").substring(30));
names[] = l.toArray(new String[0]);
// Call notifyDataSetChanged each time your array gets updated
adapter.notifyDataSetChanged();
}
#Override public void onCancelled(FirebaseError error) { }
});
}
Now write a function to show the ListView in the AlertDialog
// Declare the adapter as public and initialize it with null
private ArrayAdapter<String> adapter = null;
private void showListInDialog() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this);
LayoutInflater inflater = getLayoutInflater();
View convertView = inflater.inflate(R.layout.dialog_list, null);
alertDialog.setView(convertView);
alertDialog.setTitle("title");
ListView lv = (ListView) convertView.findViewById(R.id.lv);
if(adapter == null)
adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
// Now set the adapter
lv.setAdapter(adapter);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
alertDialog.dismiss();
}
});
alertDialog.show();
}
Now inside your onCreate function you need to set the Firebase listener first and then set the onClick function like this.
uProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showListInDialog();
}
});
#Hammad Try this modified code basing on your requirement.
query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");
AlertDialog alertDialog;
ArrayList<String> l;
uProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot != null) {
Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();
if(l == null) {
l = new ArrayList<String>();
}
l.add(newD.get("lol").substring(30));
String names[] = new String[l.size()];
for(int length=0; length < l.size(); l++) {
names[length] = l.get(length);
}
if(alertDialog == null) {
alertDialog = new AlertDialog.Builder(Activity.this).create();
LayoutInflater inflater = getLayoutInflater();
View convertView = inflater.inflate(R.layout.dialog_list, null);
alertDialog.setView(convertView);
alertDialog.setTitle("title");
ListView lv = (ListView) convertView.findViewById(R.id.lv);
} ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
lv.setAdapter(adapter);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
if(!alertDialog.isShowing()) {
alertDialog.show();
}
} else {
Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show();
}
}
...
...
});
}
});
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
/**
Retrieve lists of items or listen for additions to a list of items. This callback is triggered once for each existing child and then again every time a new child is added to the specified path. The DataSnapshot passed to the listener contains the new child's data.
**/
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
ref.addChildEventListener(childEventListener);
Usining ChildEventListener onChildAdded are call per child you have in that node. Means your code runs 3 time so dialog appers 3 time.
This is the problem
So the solution is:
While using a ChildEventListener is the recommended way to read lists of data, there are situations where attaching a ValueEventListener to a list reference is useful.
Attaching a ValueEventListener to a list of data will return the entire list of data as a single DataSnapshot, which you can then loop over to access individual children.
Even when there is only a single match for the query, the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result:
inaccessibleChild.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
//here you can access the each child of that node.
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
// ...
}
});
Well, none of the above answers really helped, though Linxy's answer is correct, I saw it after solving the probelm.
Moving all the code out and writing just this line: alertDialog.show(); inside setOnClickListener() improving my code to this:
query = mDatabase.child("child").child(anotherChild).child("yetAnotherChild");
query.orderByChild("someChild").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot != null) {
Map<String, String> newD = (Map<String, String>) dataSnapshot.getValue();
ArrayList<String> l = new ArrayList<String>();
l.add(newD.get("lol").substring(30));
String names[] = l.toArray(new String[0]);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(Activity.this);
LayoutInflater inflater = getLayoutInflater();
View convertView = inflater.inflate(R.layout.dialog_list, null);
alertDialog.setView(convertView);
alertDialog.setTitle("title");
ListView lv = (ListView) convertView.findViewById(R.id.lv);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1, names);
lv.setAdapter(adapter);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
} else {
Toast.makeText(getBaseContext(), "NULLLLL", Toast.LENGTH_SHORT).show();
}
}
...
...
});
uProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
alert11.show();
}
});
Anyway, I would like to thank all those who answered this question.
Peace.
I am developing an Android app, and I have already implemented authentication with Firebase. After logging in, in my NavigationDrawerActivity I have a ListView that I had set a FirebaseListAdapater to that gets user specific data.
In my onCreate() method I have the following:
firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser localUser = firebaseAuth.getCurrentUser();
String localUserEmail = localUser.getEmail();
String localUserEmailUniqueID = getEmailAddressUniqueID(localUserEmail);
String dbUsersRoot = "https://DATABASENAME.firebaseio.com/Users/";
String dbUniqueRefForCurrentUser = dbUsersRoot + localUserEmailUniqueID +"/parishioners";
DatabaseReference databaseReferenceCurrentUser = FirebaseDatabase.getInstance().getReferenceFromUrl(dbUniqueRefForCurrentUser);
final FirebaseListAdapter<String> firebaseListAdapter = new FirebaseListAdapter<String>(
this,
String.class,
android.R.layout.simple_list_item_2,
databaseReferenceCurrentUser
) {
#Override
protected void populateView(View v, String model, int position) {
TextView textView = (TextView) v.findViewById(android.R.id.text1);
textView.setText(model);
}
};
mListView.setAdapter(firebaseListAdapter);
Now, in my onStart() method I have added an setOnClickListener to a button that wishes to add a new item into my list , like this :
#Override
protected void onStart(){
super.onStart();
mButtonAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser localUser = firebaseAuth.getCurrentUser();
String localUserEmail = localUser.getEmail();
String localUserEmailUniqueID = getEmailAddressUniqueID(localUserEmail);
String dbUsersRoot = "https://DATABASENAME.firebaseio.com/Users/";
String dbUniqueRefForCurrentUser = dbUsersRoot + localUserEmailUniqueID +"/parishioners";
DatabaseReference databaseReferenceCurrentUser = FirebaseDatabase.getInstance().getReferenceFromUrl(dbUniqueRefForCurrentUser);
databaseReferenceCurrentUser.push().setValue(editTextNewMember.getText().toString().trim());
}
});
}
On clicking the Add Button, I'll have in my database something like this (supposing the EditText has in it the string 'capuccino'):
"luminittta" : {
"parishioners" : {
"-KX1GcEWPMy7oFWgt_3h" : "capuccino"
Now, my List will show 'capuccino' (since it's a realtime database my list will automatically get updated with the newly added value).
My question is:
How can I implement next a delete functionality that when the user long clicks an item from the ListView it gets removed?
Entire Database looks like this:
{
"Users" : {
"davidivanmircea" : {
"parishioners" : {
"-KX1FNcgSXgsMNz6QRIS" : "Gus Crick",
"-KX1FVIzzPM4nMrMvm9x" : "Florentino Williams",
"-KX1FZ27M-KS5TQZQ76u" : "Marc Raff",
"-KX1FbercKpPrl9r9tb4" : "Frederick Haddon",
"-KX1FgguOlRRN4sZKS8Z" : "Cristobal Wolfe",
"-KX1FkgwifQLIHplsZNx" : "Scott Nodal",
"-KX1Fp64Sa2QD94GR9uK" : "Odis Nevers",
"-KX1FrYK5PeuBucEiamY" : "Chauncey Mossman",
"-KX1FvIBDSrvppC3e4Ip" : "Alfonso Ignacio",
"-KX1Fy7dEHH8Z9JV-BRL" : "Douglas Hettinger",
"-KX1WdtbV4PEiscJV6E_" : "Daniel Muresan",
"-KX1WvYqekJZdWS6wGh6" : "Angelina Jolie"
}
},
"luminittta" : {
"parishioners" : {
"-KX1GYuSsgmHyGk5LQLA" : "mocha",
"-KX1G_Q130sWitNGzlAR" : "triplo",
"-KX1GaPIhuIyhV4vmLGe" : "latte",
"-KX1GcEWPMy7oFWgt_3h" : "capuccino",
"-KX1Gf7TKY3N8IQETig-" : "machiatto",
"-KX1Gh4KoYpcVpCDFI2x" : "cafe melange",
"-KX1GoCutX3XO-CRWWB3" : "ristretto",
"-KX1GpvdE5i9UR2ZaX0K" : "americano",
"-KX1Grb8S5QZu4HT9cuW" : "espresso"
}
}
}
}
Thank you very much for your help !
PS: I have modified my actual database name with 'DATABASENAME' inside the code.
Change your "populateView" to this one:
#Override
protected void populateView(View v, String model, int position) {
TextView textView = (TextView) v.findViewById(android.R.id.text1);
textView.setText(model);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mRecycleViewAdapter.getRef(position).removeValue();
Log.d("TAG", model + " removed from the list");
}
});
}
};
To remove a specific item on LongClick write this in populateView
v.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
getRef(position).removeValue();
notifyDataSetChanged();
return true;
}
});
After reading the code Nirel and Frank provided, I changed my FirebaseListAdapter into a RecyclerView succesfully and implemented my Delete functionality (on clicking the item from the list).
For the record, RecyclerView does not come with an onClickListener by itself, so anyone who will be in the same situation as I was will need to implement it. I have used http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/ and it works like a charm.
Hello guys I am for first time here so if there are some mistakes with my problem just notify me to correct my self. My problem is in the adapter I think. My application is with 3 fragment tabs. In each tab I have a ListView with some items. Also I have button in each tab that updates,deletes or adds items. I make that by popping up an AleartDialog for adding a new item or clicking on the item from the list to update it or delete it. So after I login in my application I can do what ever I want with that list. Its not a problem. I can rotate the screen and my list still updates. Changing the tabs its not a problem also. The problem comes when I go to other fragment I click on the button for adding or on some of the items for updating and the AleartDialog pops up. After that when I close it I return to the first tab. Trying to add an item doesn't update the list and I see the same items. Deleting the item from the list then throws exception IndexOutOfBounds because the item its not in the list. I think I use arrayAdapter.notifyDataSetChanged() properly. Here I will share some other code.
Like that I update my list. In the jsonObject is list the with the items.
private void fillList(Gson gson, String jsonObject) {
listWithNames.clear();
Type collectionType = new TypeToken<ArrayList<PersonalSaveDTO>>() {
}.getType();
personalSaveList = gson.fromJson(jsonObject, collectionType);
Log.wtf(TAG, "OT REQUEST: " + personalSaveList);
for (int i = 0; i < personalSaveList.size(); i++) {
listWithNames.add(personalSaveList.get(i).getName());
}
Log.wtf(TAG, "fillList: " + listWithNames);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
arrayAdapter.notifyDataSetChanged();
buttonEnable(true);
}
});
}
Like that I starts the fragment.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View viewFragment = inflater.inflate(R.layout.user_fragment, container, false);
listViewUser = (ListView) viewFragment.findViewById(R.id.listViewForUser);
addItem = (Button) viewFragment.findViewById(R.id.buttonAddUserElements);
updateList = (Button) viewFragment.findViewById(R.id.refreshListUser);
updateList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
makeRequestForList(viewFragment);
}
});
addItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addElement(viewFragment);
}
});
configureArrayAdapter(viewFragment);
setListenerForUserList(viewFragment);
if (savedInstanceState != null) {
isRequestMade = savedInstanceState.getBoolean("isRequestMade");
listWithNames = savedInstanceState.getStringArrayList("listWithNames");
personalSaveList = savedInstanceState.getParcelableArrayList("personalSaveList");
arrayAdapter.addAll(listWithNames);
arrayAdapter.notifyDataSetChanged();
}
if (!isRequestMade) {
makeRequestForList(viewFragment);
isRequestMade = true;
}
return viewFragment;
}
And here is how I create the adapter.
private void configureArrayAdapter(View view) {
listWithNames = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(view.getContext(),
R.layout.list_personal_group_fragment, R.id.adapterFragmentPersonalGroups, listWithNames);
arrayAdapter.clear();
listViewUser.setAdapter(arrayAdapter);
}