1

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;
}

}
DawidJ
  • 1,159
  • 11
  • 19
Blacky_99
  • 109
  • 1
  • 10

3 Answers3

0

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

sourabh kaushik
  • 501
  • 4
  • 20
0

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)

Marco
  • 262
  • 2
  • 13
0

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

DawidJ
  • 1,159
  • 11
  • 19