Firebase ListView is not updating in real time - android

When I make changes to the data which is displayed using ListView and DataSnapshot the data is not refreshed in real time until I restart the Activity. The ListView loads and displays all the data without any problem. Why is this happening and how to solve this ?
MainMenuRequest.java
public class MainMenuRequest extends AppCompatActivity {
String UserNameString;
DatabaseReference db;
ListView lv;
ArrayList<RequestItem> list = new ArrayList<>();
RequestItemAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu_request);
makeItem();
}
public void makeItem ()
{
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReferenceFromUrl("https://vsem-inventory.firebaseio.com/ItemRequest");
ValueEventListener valueEventListener = new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
list = new ArrayList<RequestItem>();
for(DataSnapshot dSnapshot : dataSnapshot.getChildren()) {
for(DataSnapshot ds : dSnapshot.getChildren()) {
RequestItem Ri = ds.getValue(RequestItem.class);
Ri.setRefID(ds.getKey());
Log.d("myTag",ds.getKey());
list.add(Ri);
}
}
lv = findViewById(R.id.listViewRequest);
adapter = new RequestItemAdapter(MainMenuRequest.this,list);
lv.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("DatabaseError", databaseError.getMessage()); //Don't ignore errors!
}
};
rootRef.addListenerForSingleValueEvent(valueEventListener);
}
}
RequestItemAdapter.java
public class RequestItemAdapter extends ArrayAdapter<RequestItem> {
private Context ctx;
private ArrayList<RequestItem> list;
ImageView statusimg;
Drawable lateIcon;
Drawable paidIcon;
public RequestItemAdapter(Context context, ArrayList<RequestItem> list)
{
super(context,0,list);
this.ctx = context;
this.list = list;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItem = convertView;
if(listItem == null)
listItem = LayoutInflater.from(ctx).inflate(R.layout.content_main_menu_request_list,parent,false);
final RequestItem rq = list.get(position);
final TextView tvAmount = listItem.findViewById(R.id.amountReq);
final TextView tvName = listItem.findViewById(R.id.nameReq);
final TextView tvSerial = listItem.findViewById(R.id.serialNoReq);
final TextView tvSupplier = listItem.findViewById(R.id.supplierNameReq);
final ImageView more = listItem.findViewById(R.id.moreReq);
statusimg = listItem.findViewById(R.id.statusReq);
lateIcon = listItem.getResources().getDrawable(R.drawable.late);
Drawable pendingIcon = listItem.getResources().getDrawable(R.drawable.pending);
String userName = rq.getRequestBy();
userName = userName.replace("#vsemtech.com","");
tvAmount.setText(userName);
tvName.setText(rq.getProductName());
tvSerial.setText(rq.getSerialNo());
tvSupplier.setText(rq.getCategory());
String status = rq.getStatus();
if(status.equals("REJECT"))
statusimg.setImageDrawable(lateIcon);
else if (status.equals("APPROVED"))
statusimg.setImageDrawable(paidIcon);
else if (status.equals("PENDING"))
statusimg.setImageDrawable(pendingIcon);
more.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
String RequestBy = rq.getRequestBy();
String Status = rq.getStatus();
String ProductName = rq.getProductName();
String SerialNo = rq.getSerialNo();
String Model = rq.getModel();
String Category = rq.getCategory();
String Quantity = rq.getQuantity();
String Remarks = rq.getRemarks();
showMenu(rq,more);
}
});
return listItem;
}
public void showMenu (RequestItem reqItem,ImageView More)
{
final RequestItem finalItem = reqItem;
final ImageView more = More;
final String shortRequestby = reqItem.getRequestBy().replace("#vsemtech.com","");
final DatabaseReference DeleteRef = FirebaseDatabase.getInstance().getReference().child("ItemRequest").child(shortRequestby);
final DatabaseReference DbRef = FirebaseDatabase.getInstance().getReference().child("ItemRequest").child(shortRequestby).child(finalItem.getRefID());
//Creating the instance of PopupMenu
PopupMenu popup = new PopupMenu(ctx, more);
//Inflating the Popup using xml file
popup.getMenuInflater().inflate(R.menu.menu_options_req, popup.getMenu());
//registering popup with OnMenuItemClickListener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.item_approve)
{
DeleteRef.child(finalItem.getRefID()).removeValue();
writeNewPost(new RequestItem(finalItem,"APPROVED"));
Toast.makeText(ctx,"Successfully approved request made by " + shortRequestby ,Toast.LENGTH_SHORT).show();
}
else if (itemId == R.id.item_reject)
{
DeleteRef.child(finalItem.getRefID()).removeValue();
writeNewPost(new RequestItem(finalItem,"REJECTED"));
Toast.makeText(ctx,"Successfully rejected request made by " + shortRequestby ,Toast.LENGTH_SHORT).show();
}
return true;
}
});
popup.show();//showing popup menu
}
public void writeNewPost(RequestItem item)
{
DatabaseReference dbReq = FirebaseDatabase.getInstance().getReference().child("ItemHistory").child(item.getRequestBy().replace("#vsemtech.com",""));
String key = dbReq.push().getKey();
Map<String, Object> postValues = toMap(item);
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put(key, postValues);
dbReq.updateChildren(childUpdates);
}
public Map<String, Object> toMap(RequestItem item)
{
HashMap<String, Object> result = new HashMap<>();
result.put("ProductName", item.getProductName());
result.put("SerialNo", item.getSerialNo());
result.put("Quantity", item.getQuantity());
result.put("Category",item.getCategory());
result.put("Model", item.getModel());
result.put("RequestBy", item.getRequestBy());
result.put("Status",item.getStatus());
result.put("Remarks",item.getRemarks());
return result;
}
}

You are using addListenerForSingleValueEvent() which will only listen for single value and then stop. You need to use addValueEventListener().

one way of doing this is you need to add elements in this ArrayList<RequestItem> list by making this as static in adapter class instead of the list in activity which you are passing to the adapter then you notifyDataSetChanged() function will work if you want to show changes in the list in real time

I suggest you to use the already built in library to make the list automatically updated when new data is pushed in firebase: check out this
If you want to stick with a custom implementation, define the adapter first in OnCreate callback and call adapter.notifyDataSetChanged() every time you updated your data.
If you want to insert/update/delete only one item inside your list call adapter.notifyItemChanged(position) from your adapter.
I strongly suggest you to switch to RecyclerView instead of ListView in Android (interesting comparison between them)

Related

FirebaseRecyclerAdapter model returning null values

I'm trying to make a comment system for posts on my social media app. In my database each post has a section inside of "comments" table, like so:
"hypno--######" is the title of the social media post. It Contains the comment, user id of the user who posted the comment, and a unixtimestamp when the comment was posted. Each comment is titled after the time it was posted.
This is the Comment class
public class comment {
public String uID;
public String comment_t;
public long unixTimestamp;
public comment() {
// Default constructor required for calls to DataSnapshot.getValue(User.class)
}
public comment(String uID, String comment_t, long unixTimestamp) {
this.uID = uID;
this.comment_t = comment_t;
this.unixTimestamp = unixTimestamp;
}
public String getuID() {
return uID;
}
public void setuID(String uID) {
this.uID = uID;
}
public String getComment() {return comment_t;}
public void setComment() {this.comment_t = comment_t; }
public long getUnixTimestamp() {
return unixTimestamp;
}
}
This is the Comment Adapter:
Public class Adapter_Comment extends FirebaseRecyclerAdapter<comment, Adapter_Comment.ViewHolder_com> {
private DatabaseReference mDatabase;
private static final String TAG = "RecyclerViewAdapter";
private Context mContext;
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
private static AppCompatActivity unwrap(Context context) {
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (AppCompatActivity) context;
}
public Adapter_Comment(#NonNull FirebaseRecyclerOptions<comment> options) {
super(options);
//this.mContext = mContext;
}
#NonNull
#Override
public ViewHolder_com onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_comment, parent, false);
mDatabase = FirebaseDatabase.getInstance().getReference();
return new ViewHolder_com(view);
}
#Override
protected void onBindViewHolder(#NonNull ViewHolder_com holder, int position, #NonNull comment model) {
mDatabase = FirebaseDatabase.getInstance().getReference();
long dv = model.getUnixTimestamp()*-1000;
Date df = new java.util.Date(dv);
String vv = new SimpleDateFormat("MM dd, yyyy hh:mma", Locale.ENGLISH).format(df);
holder.time.setText(vv);
String com = model.getComment();
holder.comment_text.setText(com);
mDatabase.child("users").child(model.getuID()).child("profileUrl").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists())
{
final String picUrl = snapshot.getValue(String.class);
Glide.with(holder.postPfp.getContext()).load(picUrl).into(holder.postPfp);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) { }
});
holder.postPfp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//AppCompatActivity activity = (AppCompatActivity) v.getContext();
AppCompatActivity activity = unwrap(v.getContext());
Fragment OtherProfileFragment = new OtherProfileFragment();
Bundle bundle = new Bundle();
bundle.putString("key", model.getuID());
OtherProfileFragment.setArguments(bundle);
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, OtherProfileFragment).addToBackStack(null).commit();
}
});
}
public class ViewHolder_com extends RecyclerView.ViewHolder {
TextView comment_text;
CircleImageView postPfp;
TextView time;
RelativeLayout comment_layout;
public ViewHolder_com(#NonNull View itemView) {
super(itemView);
postPfp = itemView.findViewById(R.id.iv_comment_icon);
comment_text = itemView.findViewById(R.id.tv_comment_text);
time = itemView.findViewById(R.id.tv_comment_time);
comment_layout = itemView.findViewById(R.id.comment_layout);
}
}
}
This is Comment Fragment:
public class CommentFragment extends Fragment {
private DatabaseReference mDatabase;
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
View view;
String value;
RecyclerView recyclerView;
Query query;
TextView comment_text;
long unixTime = System.currentTimeMillis() / 1000L;
public long globalUnix;
Button comment_post;
String comment_string;
Adapter_Comment adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_comment, container, false);
value = getArguments().getString("key");
mDatabase = FirebaseDatabase.getInstance().getReference();
recyclerView = view.findViewById(R.id.recyclerv_comment);
comment_text = view.findViewById(R.id.tv_comment_type);
comment_post = view.findViewById(R.id.btn_comment_post);
globalUnix = (unixTime * -1);
comment_post.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(comment_text.getText().toString() == NULL){
Toast.makeText(getActivity(), "No Comment Typed", Toast.LENGTH_LONG).show();
}
else{
comment com = new comment();
com.uID = user.getUid();
com.comment_t = comment_text.getText().toString();
com.unixTimestamp = globalUnix;
mDatabase.child("comments").child(value).child(globalUnix + "").setValue(com);
}
}
});
initRecyclerView();
return view;
}
private void initRecyclerView(){
//Log.d(TAG, "initRecyclerView: init recyclerView");
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
query = FirebaseDatabase.getInstance().getReference().child("comments").orderByValue();
FirebaseRecyclerOptions<comment> options = new FirebaseRecyclerOptions.Builder<comment>().setQuery(query, comment.class).build();
adapter = new Adapter_Comment(options);
recyclerView.setAdapter(adapter);
adapter.startListening();
adapter.notifyDataSetChanged();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Inside of the adapter I'm using the comment model, to get the uID, comment and timestamp to fill the holder, however when i set these values im getting null values. Is there something im missing when trying to connect the adapter/firebase and model/holder?
long dv = model.getUnixTimestamp()*-1000;
Date df = new java.util.Date(dv);
String vv = new SimpleDateFormat("MM dd, yyyy hh:mma", Locale.ENGLISH).format(df);
holder.time.setText(vv);
String com = model.getComment();
holder.comment_text.setText(com);
mDatabase.child("users").child(model.getuID()).child("profileUrl").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists())
{
final String picUrl = snapshot.getValue(String.class);
Glide.with(holder.postPfp.getContext()).load(picUrl).into(holder.postPfp);
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) { }
});
There's really too much going on in here, but...
As far as I can see you're creating a FirebaseUI adapter on FirebaseDatabase.getInstance().getReference().child("comments"). FirebaseUI adapters show the direct child nodes of the node you pass in, so in your case it'll create one view for the hypno---...196 node. You're trying to read a Comment object from there, but don't exist until one level lower in your JSON.
So you can:
Either show the comments for one post, by basing the adapter off of that. So: FirebaseDatabase.getInstance().getReference().child("comments").child("hypno---...196") (which the real key in there).
Or you can show one piece of information about each post, for example its key.
If you want to show a flat list of comments for all posts through the FirebaseUI adapter, you'll have to store a flat list of comments across all posts in your database too.

name is null - Custom ArrayAdapter

I have a custom ArrayAdapter that is supposed to display a users' profile image and username.
I've been following this tutorial:
Custom Android Layouts with Your Own ArrayAdapter
Yet, when I open my activity, the app crashes and says:
java.lang.NullPointerException: name is null
Which is true, since I have yet to build a feature for users to add one. Instead it should be displaying a placeholder image.(Picasso)
Here is my CustomAdapter:
public class ContactsAdapter extends ArrayAdapter<CustomContact>{
private Context context;
private List<CustomContact> contactList;
//constructor, call on creation
public ContactsAdapter(Context context, int resource, ArrayList<CustomContact> objects) {
super(context, resource, objects);
this.context = context;
this.contactList = objects;
}
public View getView(int position, View convertView, ViewGroup parent) {
//get the user we are displaying
CustomContact customcontact = contactList.get(position);
//get the inflater and inflate the XML layout for each item
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.mylist, null);
ImageView image = (ImageView) view.findViewById(R.id.friend_icon2);
TextView friend_name = (TextView) view.findViewById(R.id.Itemname);
//get & set username
String completeUsername = customcontact.getUsername();
friend_name.setText(completeUsername);
//get the image associated with this user
int imageID = context.getResources().getIdentifier(customcontact.getImageURL(), "string", context.getPackageName());
//set image
Picasso.get().load(imageID).placeholder(R.drawable.placeholder_image).resize(96, 96)
.centerCrop().into(image);
return view;
}
}
The line in question returning null is this one defining ImageID:
//get the image associated with this user
int imageID = context.getResources().getIdentifier(customcontact.getImageURL(), "string", context.getPackageName());
Here is my ContactsActivity.java
public class ContactsActivity extends ListActivity {
private DatabaseReference mFriendDatabase;
private DatabaseReference mRootRef;
private DatabaseReference mUsersDatabase;
private FirebaseAuth mAuth;
private String mCurrent_user_id;
private View mMainView;
private RecyclerView mFriendsList;
private ListView contacts_list, lstView;
private ArrayAdapter dataAdapter;
private RelativeLayout individual_contact;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts);
ArrayList<CustomContact> contactList = new ArrayList<>();
ArrayAdapter<CustomContact> adapter = new ContactsAdapter(ContactsActivity.this, 0, contactList);
mAuth = FirebaseAuth.getInstance();
mRootRef = FirebaseDatabase.getInstance().getReference();
mCurrent_user_id = mAuth.getCurrentUser().getUid();
mFriendDatabase = FirebaseDatabase.getInstance().getReference().child("friends").child(mCurrent_user_id);
mFriendDatabase.keepSynced(true);
contacts_list = (ListView) findViewById(android.R.id.list);
contacts_list.setAdapter(adapter);
individual_contact = (RelativeLayout) findViewById(R.id.mylist);
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference().child("users");
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot friendKeySnapshot: dataSnapshot.getChildren()) {
String friendKey = friendKeySnapshot.getKey();
usersRef.child(friendKey).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot friendSnapshot) {
String friendName = friendSnapshot.child("username").getValue(String.class);
String friendPicture = friendSnapshot.child("image_url").getValue(String.class);
contactList.add(
new CustomContact(friendName, friendPicture)
);
contacts_list.setAdapter(adapter);
//add event listener so we can handle clicks
AdapterView.OnItemClickListener adapterViewListener = new AdapterView.OnItemClickListener() {
//on click
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CustomContact customContact = contactList.get(position);
Intent intent = new Intent(ContactsActivity.this, MessageActivity.class);
intent.putExtra("username", customContact.getUsername());
intent.putExtra("ImageURL", customContact.getImageURL());
startActivity(intent);
}
};
//set the listener to the list view
contacts_list.setOnItemClickListener(adapterViewListener);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
}
}
To set image with Picasso you need to put an image url as parameter in the load() method but you are putting an integer id. You may try this
Picasso.get().load(customcontact.getImageURL()).placeholder(R.drawable.placeholder_image).resize(96, 96)
.centerCrop().into(image);
Please provide your ContactsActivity.java codes for further clarification.

Update listView after updating dataBase?

I have a listView of books ,I update listview by clicking on item and its work , but i have duplicate item , the old one and the new one.in my database i have just the new data. How can i also modify my listview? I'm using FireBase Database.
Update with source of my activity:
public class ListOfMyBookActivity extends AppCompatActivity {
//The elements are initialized here
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_of_my_book);
listView = (ListView) findViewById(R.id.list_book);
feedItems = new ArrayList<Book>();
dataBD= FirebaseDatabase.getInstance();
dataBaseD=FirebaseDatabase.getInstance();
updateDB=FirebaseDatabase.getInstance();
ref = dataBD.getReference("books");
refdelete=dataBaseD.getReference("books");
refUpdate=updateDB.getReference("books");
auth = FirebaseAuth.getInstance();
mDatabase = FirebaseDatabase.getInstance().getReference("books");
ref.orderByChild("date_creation").limitToLast(10).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> list = new ArrayList<String>();
for (DataSnapshot dataSnap : dataSnapshot.getChildren()) {
Book valueBook = dataSnap.getValue(Book.class);
keyId = dataSnap.getKey();
String userBd = valueBook.getId_user();
if (userBd.equalsIgnoreCase(id_user)) {
String titreLivreToDisplay = valueBook.getNom_livre();
String descLivreToDisplay = valueBook.getDesc_livre();
String prixLivreToDisplay = valueBook.getPrix_livre();
String timeToDisplay = valueBook.getDate_creation();
String filePathToDiplay = valueBook.getChemin_image();
String villeToDisplay = valueBook.getVille_livre();
String typeAnnToDisplat = valueBook.getType_annonce_selected();
String bookid = valueBook.getId_book();
item = new Book();
item.setNom_livre(titreLivreToDisplay);
item.setDesc_livre(descLivreToDisplay);
item.setPrix_livre(prixLivreToDisplay);
item.setDate_creation(timeToDisplay);
item.setChemin_image(filePathToDiplay);
item.setVille_livre(villeToDisplay);
item.setType_annonce_selected(typeAnnToDisplat);
item.setId_book(bookid);
item.setKeyIdNode(keyId);
feedItems.add(item);
}
Collections.reverse(feedItems);
listAdapter = new MyBookListAdapter(ListOfMyBookActivity.this, feedItems);
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(myClickListener);
listAdapter.notifyDataSetChanged();
}}
});
}
public AdapterView.OnItemClickListener myClickListener = new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
final int position, long arg3) {
deleteItem = position;
// The AlertDialog is created programmatically
AlertDialog.Builder alert = new AlertDialog.Builder(arg1.getContext());
nameBookEdtDlg.setText(nom);
descBookEdtDlg.setText(desc);
prixBookEdtDlg.setText(prix);
alert.setPositiveButton("Update ",
new DialogInterface.OnClickListener()
{
public void onClick (DialogInterface dialog,
int whichButton){
Query query = refUpdate.orderByChild("id_book").equalTo(bookID);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
prixSt=prixBookEdtDlg.getText().toString();
descSt=descBookEdtDlg.getText().toString();
namSt=nameBookEdtDlg.getText().toString();
Map<String, Object> result = new HashMap<String, Object>();
result.put("nom_livre", namSt);
result.put("desc_livre", descSt);
result.put("prix_livre", prixSt);
result.put("date_creation", currentDateandTimeUpdate);
refUpdate.child(keyId).updateChildren(result);
listAdapter.notifyDataSetChanged();
} });
AlertDialog alertDialog = alert.create();
try{alertDialog.show();} } };}
}
}
The Adapter :
public class MyBookListAdapter extends BaseAdapter {
public MyBookListAdapter( ListOfMyBookActivity listMyBooks, List<Book> feedItemsBooks) {
this.activity = listMyBooks;
this.feedItemsBooks = feedItemsBooks;
}
#Override
public int getCount() {
return feedItemsBooks.size();
}
#Override
public Object getItem(int location) {
return feedItemsBooks.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, final ViewGroup parent) {
final int pos = position;
if (inflater == null) {
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
if (convertView == null) {
convertView = inflater.inflate(R.layout.feed_list_item, null);
}
storageDisplayImg = FirebaseStorage.getInstance();
auth = FirebaseAuth.getInstance();
FirebaseUser userConnect = auth.getCurrentUser();
String id_user = userConnect.getUid();
mFirebaseInstance = FirebaseDatabase.getInstance();
mFirebaseDatabase = mFirebaseInstance.getReference("books");
final ImageView profilePic = (ImageView) convertView.findViewById(R.id.book_picture_display_myBook);
name = (TextView) convertView.findViewById(R.id.name_book_display_myBook);
TextView timestamp = (TextView) convertView.findViewById(R.id.timestamp_myBook);
statusMsg = (TextView) convertView.findViewById(R.id.desc_display_myBook);
prix = (TextView) convertView.findViewById(R.id.prix_display_myBook);
TextView ville = (TextView) convertView.findViewById(R.id.ville_display_myBook);
TextView typeCat = (TextView) convertView.findViewById(R.id.type_ann_to_display_myBook);
Book item = feedItemsBooks.get(position);
idLivreListAdapter=item.getId_book();
name.setText(item.getNom_livre());
if (!TextUtils.isEmpty(item.getDate_creation())) {
timestamp.setText(item.getDate_creation());
timestamp.setVisibility(View.VISIBLE);
} else {
timestamp.setVisibility(View.GONE);
}
if (!TextUtils.isEmpty(item.getDesc_livre())) {
statusMsg.setText(item.getDesc_livre());
statusMsg.setVisibility(View.VISIBLE);
} else {
statusMsg.setVisibility(View.GONE);
}
if (!TextUtils.isEmpty(item.getType_annonce_selected())) {
typeCat.setText(item.getType_annonce_selected());
typeCat.setVisibility(View.VISIBLE);
} else {
typeCat.setVisibility(View.GONE);
}
if (item.getPrix_livre() != null) {
prix.setText(item.getPrix_livre() + " DH");
prix.setVisibility(View.VISIBLE);
} else {
prix.setVisibility(View.GONE);
}
if (item.getVille_livre() != null) {
ville.setText(item.getVille_livre());
ville.setVisibility(View.VISIBLE);
} else {
ville.setVisibility(View.GONE);
}
storageRef = storageDisplayImg.getReferenceFromUrl(item.getChemin_image());
Log.e(" ", " storageRef " + storageRef.toString());
if (item.getChemin_image() != null && id_user != null) {
Glide.with(convertView.getContext())
.using(new FirebaseImageLoader())
.load(storageRef)
.into(profilePic);
profilePic.setVisibility(View.VISIBLE);
} else {
profilePic.setVisibility(View.GONE);
}
return convertView;
}
}
My question is not duplicated I tried the proposed solutions but it does not work.
Not sure if this if your problem, but most of that firebase code isn't all necessary...
Notice you call getNom_livre (and others) and then call setNom_livre (and others) with the exact same value?
You also make a new Book when you already have one.
Book valueBook = dataSnap.getValue(Book.class); // This is a Book
keyId = dataSnap.getKey();
String userBd = valueBook.getId_user();
if (userBd.equalsIgnoreCase(id_user)) {
String titreLivreToDisplay = valueBook.getNom_livre();
...
item = new Book(); // Why do you need a new one?
item.setNom_livre(titreLivreToDisplay);
...
feedItems.add(item);
}
First, you should move this before the firebase method. There is no need to recreate the adapter every data update.
listAdapter = new MyBookListAdapter(ListOfMyBookActivity.this, feedItems);
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(myClickListener);
ref.orderByChild("date_creation")...
but i have duplicate item , the old one and the new one
You simply need to clear the adapter to remove old data and add the new stuff
ref.orderByChild("date_creation")
.limitToLast(10)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Remove old data
feedItems.clear();
// Add new data
for (DataSnapshot dataSnap : dataSnapshot.getChildren()) {
Book valueBook = dataSnap.getValue(Book.class);
keyId = dataSnap.getKey();
String userBd = valueBook.getId_user();
if (userBd.equalsIgnoreCase(id_user)) {
valueBook.setKeyIdNode(keyId);
feedItems.add(valueBook);
}
}
Collections.reverse(feedItems);
listAdapter.notifyDataSetChanged(); // Tell adapter of new data
Use feedItems.clear() before getting updated data from firebase.
Try this:
ref.orderByChild("date_creation").limitToLast(10).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
feedItems.clear();
.............
..................
}
});
try
feedItems.remove(position);
// listView.invalidateViews();
arrayAdapter.notifyDataSetChanged();
use this in your adapter
public void dataSetChanged(ArrayList<Movie>list)
{
this.list=list;
this.notifyDataSetChanged();
}
and use it like this
upadte your list data and after that use below line
customListViewAdapter.dataSetChanged(movieList);
use this for update your list
notifyDataSetChanged()

Sort ArrayList<HashMap<String,Object>> from biggest value on Top

I want to sort an ArrayList of HashMaps
ArrayList < HashMap < String,Object>>
in the following class:
public class NotificationFragment extends ListFragment {
private static final String TAG = "NotificationFragment";
private DatabaseReference mDatabaseReference;
private ProgressBar mProgressBar;
String[] from = {"TITLE","BODY","TIME"};
int[] to = {R.id.single_notification_row_title,
R.id.single_notification_row_body,
R.id.single_notification_row_time};
ArrayList<HashMap<String,Object>> data;
SimpleAdapter adapter;
public NotificationFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "onCreateView");
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_notification, container, false);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Set Activity title
getActivity().setTitle(R.string.Notifications);
mDatabaseReference = FirebaseDatabase.getInstance().getReference()
.child("Notification").child("Android");
Query query = mDatabaseReference.orderByChild("title");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(final DataSnapshot dataSnapshot) {
getNewData((Map<String,Object>)dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getActivity(), R.string.Something_went_wrong_retry, Toast.LENGTH_SHORT).show();
}
});
}
private void cancelNotification(Activity activity, int notifyId) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager nMgr = (NotificationManager) activity.getSystemService(ns);
nMgr.cancel(notifyId);
}
private void getNewData (Map<String,Object> mapDatabase){
mProgressBar = (ProgressBar)getActivity().findViewById(R.id.progressBarNotifications);
data = new ArrayList<>();
try{
//Iterate through each notification
for(Map.Entry<String,Object> entry : mapDatabase.entrySet()){
Log.e(TAG, "ForEach entered");
Map singleNotification = (Map)entry.getValue();
//Fill the list
String title = (String) singleNotification.get("title");
String body = (String) singleNotification.get("body");
String time = (String) singleNotification.get("time");
String timeLong = (String) singleNotification.get("timeStamp");
HashMap<String,Object> map = new HashMap<>();
map.put("TITLE", title);
map.put("BODY", body);
map.put("TIME", time);
map.put("timeLong", timeLong);
data.add(map);
Log.d(TAG,"data.add(map)");
Log.d(TAG,"data.size = " + data.size());
}
for(HashMap<String, Object> myMap: data) {
for(Map.Entry<String, Object> mapEntry: myMap.entrySet()) {
String key = mapEntry.getKey();
String value = (String) mapEntry.getValue();
if(key.equals("timeLong")){
Log.d(TAG,"timeLong = " + value);
//?????????HOW TO SORT by LONG VALUE ??????????
}
}
}
//Adapter
adapter = new SimpleAdapter
(getActivity(),data,R.layout.single_notification_row ,from,to);
setListAdapter(adapter);
Log.d(TAG,"setListAdapter(adapter)");
}catch (NullPointerException e){
Toast.makeText(getActivity(), R.string.No_Notifications, Toast.LENGTH_SHORT).show();
}
if(mProgressBar.getVisibility() == View.VISIBLE){
mProgressBar.setVisibility(View.GONE);
}
cancelNotification(getActivity(), 0);
}
#Override
public void onStart() {
super.onStart();
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(getActivity(), "HI", Toast.LENGTH_SHORT).show();
}
});
}
}
I get the following sorting order:
Screenshot
Please note that I have one single Long item (called "timeLong") in every ArrayList item.
Thank you in advance,
Gaetano
,I suggest you to create a class which contains 4 properties :
String title;
String body;
String time;
long timeLong;
Lets say the name of the class is Instance. When you get the data, create an instance of this class and set the properties of this instance instead of having 4 string values.
Change your ArrayList to this ArrayList<Instance> myList = ArrayList();
Create a class
public class SortingClass implements Comparator<Instance>
{
public int compare(Instance left, Instance right){
return left.timeLong < right.timeLong ? 1 : -1;
}
And for sorting
Collections.sort(myList,new SortingClass())

Recycler Adapter onclick Item

I have implemented the firebase recycler like this
public class HomeActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final String REQUIRED = "Required";
// [START declare_database_ref]
private DatabaseReference mDatabase;
// [END declare_database_ref]
private FirebaseAuth mAuth;
private static String LOG_TAG = "CardViewActivity";
public static class PostHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View mView;
public PostHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mView = itemView;
}
public void setName(String name) {
TextView field = (TextView) mView.findViewById(R.id.name);
field.setText(name);
}
public void setText(String text) {
TextView field = (TextView) mView.findViewById(R.id.body);
field.setText(text);
}
public void setImage(String image){
ImageView pp = (ImageView) mView.findViewById(R.id.image);
Picasso.with(Application.getAppContext()).load(image).placeholder(R.drawable.nodp).error(R.drawable.nodp).transform(new CircleTransform()).into(pp);
}
#Override
public void onClick(View mView) {
//what to do here
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
findViewById(R.id.progressBar3).setVisibility(View.VISIBLE);
findViewById(R.id.nopost).setVisibility(View.GONE);
//mListview = (ListView) findViewById(R.id.listview);
mAuth = FirebaseAuth.getInstance();
//the post list shit is happening here
final DatabaseReference root = FirebaseDatabase.getInstance().getReference();
FirebaseUser user = mAuth.getCurrentUser();
DatabaseReference postRef = root.child("users").child(user.getUid().toString()).child("posts");
RecyclerView recycler = (RecyclerView) findViewById(R.id.recyclerview);
recycler.setHasFixedSize(true);
recycler.setLayoutManager(new LinearLayoutManager(this));
FirebaseRecyclerAdapter mAdapter = new FirebaseRecyclerAdapter<PostList, PostHolder>(PostList.class, R.layout.row_one, PostHolder.class, postRef) {
#Override
public void populateViewHolder(PostHolder postViewHolder, PostList postList, int position) {
//try catch block to catch events of no posts, it will most likely return a null error, so im catching it, else
//find its exception and catch it
try {
String firstname = postList.getFirstname();
String lastname = postList.getLastname();
firstname = firstname.substring(0, 1).toUpperCase() + firstname.substring(1); //convert first string to uppercase
lastname = lastname.substring(0, 1).toUpperCase() + lastname.substring(1);// same thing happening here
String name = (firstname + " " + lastname); // concatenate firstname and lastname variable.
postViewHolder.setName(name);
postViewHolder.setText(postList.getBody()); // set the vew holder
//note that picasso view holder was applied in the view holder instead
String image = postList.getImgUrl().toString();
postViewHolder.setImage(image);
findViewById(R.id.progressBar3).setVisibility(View.GONE);
}
catch(NullPointerException e) {
findViewById(R.id.nopost).setVisibility(View.VISIBLE);
}
}
};
recycler.setAdapter(mAdapter);
}
}
and it works perfectly for my use case, I have gone through questions about how to set up onClick listeners for recycler adapter, and I think I've got it as seen in my code above.
My question is:
minor issue: when an item is clicked, I want to pass data through an intent to another activity to display details about the post. I can achieve this through intent.putExtra() on my ViewHolder as referenced by another question. But my problem is that my view holder class is outside the activity's onCreate() (that's the only way it seemed to work) so I can't call start activity from within ViewHolder,
major issue: since PostList, from which my data is from, is not yet set in the ViewHolder, so I can't put postList.getName() and getBody() in an intent, but I think it would be okay if my onClick() can go inside the firebase block itself, here:
FirebaseRecyclerAdapter mAdapter = new FirebaseRecyclerAdapter<PostList, PostHolder>(PostList.class, R.layout.row_one, PostHolder.class, postRef) {
#Override
public void populateViewHolder(PostHolder postViewHolder, PostList postList, int position) {
//try catch block to catch events of no posts, it will most likely return a null error, so im catching it, else
//find its exception and catch it
try {
String firstname = postList.getFirstname();
String lastname = postList.getLastname();
firstname = firstname.substring(0, 1).toUpperCase() + firstname.substring(1); //convert first string to uppercase
lastname = lastname.substring(0, 1).toUpperCase() + lastname.substring(1);// same thing happening here
String name = (firstname + " " + lastname); // concatenate firstname and lastname variable.
postViewHolder.setName(name);
postViewHolder.setText(postList.getBody()); // set the vew holder
//note that picasso view holder was applied in the view holder instead
String image = postList.getImgUrl().toString();
postViewHolder.setImage(image);
findViewById(R.id.progressBar3).setVisibility(View.GONE);
}
catch(NullPointerException e) {
findViewById(R.id.nopost).setVisibility(View.VISIBLE);
}
}
//onclick goes here with all the put extra and startactivity stuff
};
recycler.setAdapter(mAdapter);
You mean that you cannot get the origin activity to create the intent? have you tried getContext(), getActivity() or getBaseContext()?
Context context = getContext();
final Intent intent = new Intent(context, FirstActivity.class);
// all your stuff
context.startActivity(intent);
If you want to perform good item click functionality with a proper way then create a separate class for FirebaseRecyclerAdapter and use Interface as item click listener so you can perform intent functionality from HomeActivity.
OR
Create reference of HomeActivity class and use that reference at
#Override
public void onClick(View mView) {
//what to do here
//mcontect will be your class reference
Intent i = new (mcontext,SecondActivity.class);
startActivity(i);
}

Categories

Resources