user4744059
user4744059

Reputation:

Android Firebase Database Automatic Refresh UPDATE 2

I have implemented Firebase Database and can successfully add items to it and then display them on a RecyclerView. I also managed to implement Deletion of a child of a database which is successful BUT I need to restart activity to see changes on my phone's screen. For example: when I press Delete on my list item, it disappears from Database instantly but I need to restart the activity to see the change. Here is my code snippets:

 private void attachDatabaseReadListener() {

    queryRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {
            locationCurrent = dataSnapshot.getValue(LocationCurrent.class);
            locationCurrent.setRefKey(dataSnapshot.getKey());
            mLocationAdapter.add(locationCurrent);

        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            locationCurrent = dataSnapshot.getValue(LocationCurrent.class);


        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

}

I believe I should work on onChildRemoved but have no idea where to start. My main Idea was to repopulate recyclerview using for loop but locationCurrent object I got from datasnapshot is null.

Any ideas where should I start looking for solution? I have also considered to run addValueEventListener method on my query but I run into the problem where I get multiple copies of my single child

UPDATE Referring to some comments here is my adapter

public class LocationAdapter extends ArrayAdapter<LocationCurrent> {



public LocationAdapter(Context context, int resource, List<LocationCurrent> objects) {
    super(context, resource, objects);
}

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = ((Activity) getContext()).getLayoutInflater().inflate(R.layout.item_location, parent, false);
    }

    LocationCurrent currentLocation = getItem(position);

    TextView nameTextView = (TextView) convertView.findViewById(R.id.nameTextView);

    TextView descriptionTextView = (TextView) convertView.findViewById(R.id.descriptionTextView);


    nameTextView.setText(currentLocation.getName());
    descriptionTextView.setText(currentLocation.getDescription());



    return convertView;
}

}

By the way - my Ref Key which is used in locationCurrent class is transient variable and thus not visible in Database.

UPDATE2

After all day of working, I still did not manage to get the item off the adapter as soon it is deleted. Instead - I came up with a temporary solution - I added a recreate() method inside my onChildRemoved and it does it's job. (Not a good practice but still - something)

Upvotes: 0

Views: 3350

Answers (1)

Nicholas
Nicholas

Reputation: 1980

Basically, this is how I did a removal method.

            /**
             * This removes the CardView from the RecyclerView, allowing us to create a delete request
             *
             * http://stackoverflow.com/questions/27293960/swipe-to-dismiss-for-recyclerview/30601554#30601554
             *
             * @param viewHolder
             * @param direction
             */
            @Override
            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
                // First find the position of the card
                // https://www.learn2crack.com/2016/02/custom-swipe-recyclerview.html
                int position = viewHolder.getAdapterPosition();

                // Connect to the database, identify which card was swiped via the RecyclerViewAdapter
                DatabaseReference currRef = adapter.getRef(position);

                // Get it out of the DB
                currRef.removeValue();
            }

The following code above should give you a rough idea of the deletion process. You need to retrieve the index of the element you want to remove. In your context, your location key be binded somehow.

Just FYI, here's the populateViewHolder based a FirebaseRecyclerAdapter.

                    /**
                     * Populating the RecyclerView..
                     *
                     * @param viewHolder
                     *
                     *
                     * @param task
                     *
                     *
                     * @param position
                     * With the use of position, we can obtain the key of from the FirebaseDatabase
                     *
                     * http://stackoverflow.com/questions/37568703/how-to-get-keys-and-values-using-firebaselistadapter
                     */
                    @Override
                    protected void populateViewHolder(TaskViewHolder viewHolder, Tasks task, int position) {
                        // Get the key of the Tasks object
                        //String currentKey = getRef(position).push().getKey();
                        //final String currentKey = getRef(position).toString(); // This returns the object URL from Firebase
                        final String currentKey = getRef(position).getKey();
                        Log.d(TAG, currentKey.toString());
                        Log.d(TAG, "Image: " + task.getImageUrl());

                        // Perform some DateTime formatting from the ISO8601 format

                        // Basically we need to attach the task to the viewHolder so that
                        // the cards can instantiate their view properly
                        viewHolder.setTaskName(task.getTaskName());
                        viewHolder.setTaskDesc(task.getTaskDescription());
                        viewHolder.setTaskDate(task.getTaskDeadline());
                        viewHolder.setTaskImage(task.getImageUrl());

                        final Intent updateView = new Intent(getActivity(), UpdateTaskActivity.class);

                        // Implement Serializable on the Tasks object,
                        // Push the object directly via updateView.putExtra
                        // That way we can have everything we need in the object.

                        //updateView.putExtra("TaskName", task.getTaskName());
                        //updateView.putExtra("TaskDesc", task.getTaskDescription());
                        updateView.putExtra("TaskObject", task);
                        updateView.putExtra("Key", currentKey);

                        viewHolder.mView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                /**
                                 * How to provide a foundation to animate cards
                                 *
                                 * http://stackoverflow.com/questions/27300441/how-do-i-expand-cardviews-to-show-more-detail-like-google-keep-cards
                                 */
                                //Toast.makeText(getActivity(), currentKey, Toast.LENGTH_LONG).show(); // Test Line to Showcase the Key.

                                ActivityOptionsCompat options =
                                        ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(),
                                                v,   // The view which starts the transition
                                                getString(R.string.transition_taskcard)    // The transitionName of the view we’re transitioning to
                                        );

                                ActivityCompat.startActivity(getActivity(), updateView, options.toBundle());
                            }
                        });
                    }

Just showing this example to let you know that both your view and your deletion code must be dynamic.

If you're doing a dynamic view instead, you an refer to the documentation here https://github.com/firebase/emberfire

UPDATE Since you just added your adapter, it is also possible to have an onClickListener within getView to perform any removal as such if you intend to.

Upvotes: 1

Related Questions