7

I've got a ListFragment and a custom adapter.

From the adapter I get the onClick event from a button defined in the rows. In the onClick method I get some id, which I'd like to pass to the ListFragment to do some stuff.

How can I call the method showTask in the ListFragment from the adapter?

listfragment

public class TaskListFragment extends ListFragment{

    /* ... */

    @Override
    public void onCreate(Bundle savedInstanceState) {       
        super.onCreate(savedInstanceState);
        mAdapter = new TaskListAdapter(getActivity(), data);        
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
    {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(mAdapter);
    }   

    public void showTask(long id) {

        FragmentTransaction ft = getFragmentManager().beginTransaction();

        TaskFragment taskFragment = new TaskFragment();

        Bundle args = new Bundle();
        args.putLong("id", id);
        taskFragment.setArguments(args);

        ft.replace(R.id.fragment_container, taskFragment);
        ft.commit();         
    }
}

adapter

public class TaskListAdapter extends ArrayAdapter<Task>{

    /* ... */

    private OnClickListener mOnClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            long id = (Integer) v.getTag();
            // how can I call showTask(id) ?
        }
    };
}
rae1
  • 6,066
  • 4
  • 27
  • 48
jul
  • 36,404
  • 64
  • 191
  • 318
  • Why is your onClick method in the adapter and not in the activity? – Iulia Barbu Mar 01 '13 at 15:17
  • 1
    Let your fragment implement `IShowTask` interface (which has `showTask` method) then let adapter have `setShowTaskListener(IShowTask )` method ... then ... you are the programmer, don't ya? :) – Selvin Mar 01 '13 at 15:19
  • I've posted an answer the way you want it, but you shouldn't create `OnClickListeners` for every view. You should consider putting an `OnListItemClickListener` on your `ListView`. – tolgap Mar 01 '13 at 15:24

2 Answers2

16

A common solution is for the adapter to be an inner class of the fragment, so it can just call the method directly.

Or, pass the fragment (or some interface implemented by the fragment) to the adapter via its constructor.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • @CommomsWare You can say I am a bad programmer, but I wouldn't be able to solve a lot of my problems if it weren't for you :) – VipulKumar Dec 03 '14 at 12:04
15

Create your adapter like this:

@Override
public void onCreate(Bundle savedInstanceState) {       
    super.onCreate(savedInstanceState);
    mAdapter = new TaskListAdapter(getActivity(), data, TaskListFragment.this);        
}

Which would change your adapter constructor to:

public TaskListAdapter(Context context, List<Task> data, TastListFragment fragment) {
    this.fragment = fragment;
}

And now, you have an object that points to your TaskListFragment:

private OnClickListener mOnClickListener = new OnClickListener() {
    @Override
    public void onClick(View v) {
        long id = (Integer) v.getTag();
        fragment.showTask(id);
    }
};
tolgap
  • 9,629
  • 10
  • 51
  • 65
  • 6
    Thanks, it works, but I'll use an interface implemented in the Fragment instead. – jul Mar 01 '13 at 15:34
  • For noobs, here is an implementation of interface in second half of the answer. http://stackoverflow.com/a/12142492/609782 – Darpan Aug 27 '15 at 13:16