2

I am new to android development, I used Two Viewholder in My adapter ONE FOR PHOTO (PHOTOVIEWHOLDER) ,ANOTHER FOR VIDEO (VideoVIEWHOLDER)

MY Problem is I have a function I HAVE PASSED ONE VIEWHOLDER (Photoviewholder) I need to use this same function to my (VideoViewholder) . Instead of repeating the same function twice , I thought is there is other anyway I can do this

  private void addNewlike(final PhotoHolder holder){
    Log.d(TAG, "addNewlike: adding new like ");
    String newLikeID = mReference.push().getKey();
    Likes likes = new Likes();
    likes.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
    mReference.child(mContext.getString(R.string.dbname_photos))
            .child(holder.photo.getPhoto_id())
            .child(mContext.getString(R.string.field_likes))
            .child(newLikeID)
            .setValue(likes);
    mReference.child(mContext.getString(R.string.dbname_user_photos))
            .child(holder.photo.getUser_id())
            .child(holder.photo.getPhoto_id())
            .child(mContext.getString(R.string.field_likes))
            .child(newLikeID)
            .setValue(likes);
    holder.heart.toggleLike();
}


  private void addNewlike(final VideoViewHolder holder){
    Log.d(TAG, "addNewlike: adding new like ");
    String newLikeID = mReference.push().getKey();
    Likes likes = new Likes();
    likes.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
    mReference.child(mContext.getString(R.string.dbname_photos))
            .child(holder.photo.getPhoto_id())
            .child(mContext.getString(R.string.field_likes))
            .child(newLikeID)
            .setValue(likes);
    mReference.child(mContext.getString(R.string.dbname_user_photos))
            .child(holder.photo.getUser_id())
            .child(holder.photo.getPhoto_id())
            .child(mContext.getString(R.string.field_likes))
            .child(newLikeID)
            .setValue(likes);
    holder.heart.toggleLike();
}





 public class GestureListener extends GestureDetector.SimpleOnGestureListener{

    PhotoHolder mHolder;
    public GestureListener(PhotoHolder holder) {
        mHolder = holder;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.d(TAG, "onDoubleTap: double tap detected.");

        Log.d(TAG, "onDoubleTap: clicked on photo: " + mHolder.photo.getPhoto_id());

         DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
        Query query = reference
                .child(mContext.getString(R.string.dbname_photos))
                .child(mHolder.photo.getPhoto_id())
                .child(mContext.getString(R.string.field_likes));
        query.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for(DataSnapshot singleSnapshot : dataSnapshot.getChildren()){

                    String keyID = singleSnapshot.getKey();
                    //case1: Then user already liked the photo
                    if(mHolder.likephotobycurrentUser
                            && singleSnapshot.getValue(Likes.class).getUser_id()
                                    .equals(FirebaseAuth.getInstance().getCurrentUser().getUid())
                            ){
                        mReference.child(mContext.getString(R.string.dbname_photos))
                                .child(mHolder.photo.getPhoto_id())
                                .child(mContext.getString(R.string.field_likes))
                                .child(keyID)
                                .removeValue();
  ///                         mReference.child(mContext.getString(R.string.dbname_user_photos))
 //                                    .child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                                .child(mHolder.photo.getUser_id())
                                .child(mHolder.photo.getPhoto_id())
                                .child(mContext.getString(R.string.field_likes))
                                .child(keyID)
                                .removeValue();


                        mHolder.heart.toggleLike();
                        getLikesString(mHolder);
                    }
                    //case2: The user has not liked the photo
                    else if(!mHolder.likephotobycurrentUser){
                        //add new like
                        addNewlike(mHolder);
                        break;
                    }
                }
                if(!dataSnapshot.exists()){
                    //add new like
                    addNewlike(mHolder);
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        return true;
    }
}
new learner
  • 111
  • 2
  • 12

3 Answers3

2

You can create an interface that both your holders will implement, and have one function that takes that interface as argument.

For example:

public interface MyInterface {
    Photo getPhoto(); // I assume your holder.photo returns a photo class here but feel free to replace by whatever is correct
    Heart getHeart();
}

then you holders:

public PhotoHolder implements MyInterface { // keep extension if you have one
    Photo photo;
    Heart heart;
    // all your previous methods

    // implement the interface
    @Override
    public Photo getPhoto() { return photo; }

    @Override
    public Heart getHeart() { return heart; }
}

and finally your function:

private void addNewlike(final MyInterface holder){
    Log.d(TAG, "addNewlike: adding new like ");
    String newLikeID = mReference.push().getKey();
    Likes likes = new Likes();
    likes.setUser_id(FirebaseAuth.getInstance().getCurrentUser().getUid());
    mReference.child(mContext.getString(R.string.dbname_photos))
            .child(holder.getPhoto().getPhoto_id())
            .child(mContext.getString(R.string.field_likes))
            .child(newLikeID)
            .setValue(likes);
    mReference.child(mContext.getString(R.string.dbname_user_photos))
            .child(holder.getPhoto().getUser_id())
            .child(holder.getPhoto().getPhoto_id())
            .child(mContext.getString(R.string.field_likes))
            .child(newLikeID)
            .setValue(likes);
    holder.getPhoto().toggleLike();
}

and it should work as expected

Macmist
  • 713
  • 3
  • 11
2

Define abstract class of type MyBaseViewHolder which declares methods and attributes found in your PhotoHolder and VideoViewHolder.

Refactor your private void addNewlike functions to

private void addNewlike(final MyBaseViewHolder holder)

and pass in whichever ViewHolder you need.

Click the link to learn more about abstract classes, they are super useful !

Community
  • 1
  • 1
2Dee
  • 8,609
  • 7
  • 42
  • 53
  • Thanks 2dee for your answer ill will try it now – new learner Sep 26 '18 at 09:14
  • So I need to create a class (Abstract class) and that class should have all methods which photoViewholder and vedioViewholder has .. by the way thanks for sharing link I learned what abstract class is – new learner Sep 26 '18 at 09:16
  • Yes, that is what I mean. Make sure you do need 2 classes though, are there many differences between the 2 ViewHolder classes you have ? – 2Dee Sep 26 '18 at 09:24
  • 2 classes ...?? should two viewholder class implements The abstract class ?? – new learner Sep 26 '18 at 09:26
  • Indeed, correct again ! Check out @Macmist answer, simply replace interface with abstract class if you need your variables to not be constants. You should end up with 3 classes, 1 abstract and 2 implementing sub-classes (your ViewHolder for photo and for video). If you still can't decide if you need an interface or an abstract class, read [this question](https://stackoverflow.com/questions/761194/interface-vs-abstract-class-general-oo) and its answers, a lot to be learned there ;) – 2Dee Sep 26 '18 at 09:38
  • I got it but how can I get the item from it like if there is a imageView or TextView `image = (ImageView) view.findViewById(R.id.photo_iimage); ` ,**And also I have a gestureListner here for adding like** I have updated the code please help ..also thanks for time – new learner Sep 26 '18 at 12:18
  • You can create an abstract getImageView() method that you implement differently in each viewHolder but you can still call the method in the same way for both. You would then need to modify your gesture listener to accept the abstract class rather than an implementation. Beyond that, I encourage you to look at how you can [decouple some of your classes](https://www.geeksforgeeks.org/coupling-in-java/), maybe something could be improved there. – 2Dee Sep 26 '18 at 12:42
  • Something about long discussions: it should be avoided in the comments section. The reason is because your question evolves as we go. Please try to keep to the 1 question <-> 1 answer model to keep things clear for future readers who might not understand the "history" of your question. The way to go in my opinion should be: ask a question -> accept an answer -> if the answer you received makes you wonder about something else in your project -> look for duplicates of that new question -> if you didn't find any duplicate, post a new question. Hoping this helps also to feel comfortable in SO ;) – 2Dee Sep 26 '18 at 12:47
  • is it ok to use only one view holder with 2 view item ?? – new learner Oct 04 '18 at 12:17
  • Yes https://stackoverflow.com/questions/26245139/how-to-create-recyclerview-with-multiple-view-type – 2Dee Oct 04 '18 at 12:53
  • No not like that ??@2dee I want use only one viewholder for 2 view type – new learner Oct 04 '18 at 13:08
1

Pass base class of VideoViewHolder and PhotoHolder

private void addNewlike(final BaseClass holder)
Maksym V.
  • 2,877
  • 17
  • 27