'Android Studio - how to update Fragment's UI onButtonClick in a listview using BaseAdapter

The structure:

(1) Activity's FrameLayout -> (2) Fragment's ListView -> (3) Base Adapter

There are buttons such as like and reply in every row in the layout.

Whenever user hits the like button, I will have to change a TextView's text in the (1) Activity.

I couldn't find a solid answer thru searching.

So

I want communication between Adapter and Fragment.

Button click in BaseAdapter -> update UI in Activity(which contains fragment)

public class ForumDetailCommentFragment extends Fragment {

    private static final String ARG_COMMENTS = "ARG_COMMENTS";

    private ArrayList<Comment> mComments;

    public static ForumDetailCommentFragment newInstance(ArrayList<Comment> _comments) {

        Bundle args = new Bundle();
        args.putSerializable(ARG_COMMENTS, _comments);
        ForumDetailCommentFragment fragment = new ForumDetailCommentFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mComments = (ArrayList<Comment>) getArguments().getSerializable(ARG_COMMENTS);
        organizeComments();

        // adapter
        ListView lv_comments = view.findViewById(R.id.frag_forum_detail_comments_lv);
        lv_comments.setAdapter(new CommentAdapter(getActivity(), mComments));
        lv_comments.setDivider(null);
    }
}
public class CommentAdapter extends BaseAdapter {

    public static final String TAG = "ForumAdapter.TAG";

    // BASE ID
    private static final long BASE_ID = 0x1011;
    // reference to our owning screen(context)
    private Context mContext;
    // reference to our collection
    private Comment mComment = null;
    private ArrayList<Comment> mCollection;

    public CommentAdapter(Context _context, ArrayList<Comment> _collection) {
        this.mContext = _context;
        this.mCollection = _collection;
    }

    @Override
    public int getCount() {
        if(mCollection != null) return mCollection.size();
        return 0;
    }

    @Override
    public Object getItem(int position) {
        if(mCollection != null && position >= 0 && position < mCollection.size()){
            return mCollection.get(position);
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
        return BASE_ID + position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder vh = null;
        mComment = (Comment) getItem(position);

        if(convertView == null){
            convertView = LayoutInflater.from(mContext).inflate(R.layout.lv_comment_layout, parent, false);
            vh = new ViewHolder(convertView);
            convertView.setTag(vh);
        }else{
            vh = (ViewHolder) convertView.getTag();
        }

        if( mComment != null){


//            vh.tv_filter_league.setFocusable(false);
//            vh.tv_filter_league.setFocusableInTouchMode(false);
//            vh.tv_filter_category.setFocusable(false);
//            vh.tv_filter_category.setFocusableInTouchMode(false);

            // TODO: loop through user's like list.
            // TODO: if contains, change the icon's color

            if(mComment.getLayer() == 0) vh.child_divider.setVisibility(View.GONE);
            else vh.child_divider.setVisibility(View.VISIBLE);


            vh.iv_emblem.setImageResource(mComment.getAuthorEmblem(mContext));
            vh.tv_author.setText(mComment.getAuthorUser().getUName());
            vh.tv_timestamp.setText(mComment.getDateTimestamp());
            vh.tv_desc.setText(mComment.getMentionId() + mComment.getDesc());

            vh.tv_like.setText(String.valueOf(mComment.getLike()));
            vh.tv_ycard.setText(String.valueOf(mComment.getYCards()));

            vh.btn_reply.setOnClickListener(onReplyTap);
            vh.btn_like.setOnClickListener(onLikeTap);
            vh.btn_ycard.setOnClickListener(onYCardTap);
        }
        return convertView;
    }

    View.OnClickListener onLikeTap = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //DBUtil.forum_update_like_on_comment(mContext, UPDATE_LIKE, mComment.getId());
        }
    };

    View.OnClickListener onYCardTap = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //DBUtil.forum_update_ycard_on_comment(mContext, UPDATE_LIKE, mComment.getId());
        }
    };

    View.OnClickListener onReplyTap = new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    };

    static class ViewHolder{

        // TODO:
        LinearLayout child_divider;
        ImageView iv_emblem;
        TextView tv_author, tv_timestamp, tv_desc, tv_like, tv_ycard, btn_reply;
        ImageButton btn_like, btn_ycard;


        public ViewHolder(View _layout){

            child_divider = _layout.findViewById(R.id.lv_base_forum_detail_divider_layer_2);

            iv_emblem = _layout.findViewById(R.id.lv_base_forum_detail_iv_emblem);

            tv_author = _layout.findViewById(R.id.lv_base_forum_detail_tv_uname);
            tv_desc = _layout.findViewById(R.id.lv_base_forum_detail_tv_desc);
            tv_timestamp = _layout.findViewById(R.id.lv_base_forum_detail_tv_timestamp);

            tv_like  = _layout.findViewById(R.id.lv_base_forum_detail_tv_like);
            tv_ycard = _layout.findViewById(R.id.lv_base_forum_detail_tv_ycard);

            btn_reply = _layout.findViewById(R.id.lv_base_forum_detail_btn_reply);
            btn_like = _layout.findViewById(R.id.lv_base_forum_detail_btn_like);
            btn_ycard = _layout.findViewById(R.id.lv_base_forum_detail_btn_ycard);
        }
    }
}


Solution 1:[1]

Create an interface like:

public interface Callback {
    public void OnFavoriteClicked()
}

And make your fragment implements it. On your adapter, you should create a variable of this interface type (named callback, for example) and reference it from the fragment. From constructor

Adapter adapter = new Adapter(this@Fragment)

or some set method

adapter.setCallback(this)

Later, you can invoke the interface methods from your adapter like this:

callback.OnFavoriteClicked()

And the override method you must implement in the fragment should be called.

Example in Kotlin:

class Adapter() ... {
    
 interface Callback {
       fun action()
    }
    
    private var callback: Callback? = null

    fun setListener(callback: Callback) {
       this.callback = callback
    }
    
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
       holder.itemView.setOnClickListener {
         callback?.action()
       }
    }

...

class ExampleFragment : Fragment, Adapter.Callback {

    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val adapter = Adapter()
        adapter.setListener(this)
    }

    override fun action() {
        //Callback from adapter
    }

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1