Android RecyclerView how to setup click listener - casting class to interface

I'm trying to understand how to implement click handler in RecyclerView. This is a piece of code that does click handler successfully.

public class MainActivityFragment extends Fragment implements AdapterView.OnItemClickListener {
private RecyclerView mList;
private SimpleAdapter mAdapter;

public MainActivityFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    mList = (RecyclerView) rootView.findViewById(R.id.recyclerView);
    LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
    mAdapter = new SimpleAdapter();

    mAdapter.setOnItemClickListener(this);
    mList.setAdapter(mAdapter);

    return rootView;
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    Toast.makeText(getActivity(), "Clicked: " + position + ", index " + mList.indexOfChild(view) + "VIew: " + view.getClass(),
            Toast.LENGTH_SHORT).show();
}

SimpleAdapter.java

public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.GameTileHolder> {

private AdapterView.OnItemClickListener mOnItemClickListener;

public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
        mOnItemClickListener = onItemClickListener;
    }
}

This example uses so called "loose coupling" which by definition a class is cast to an interface. Why isn't there an explicit cast to AdapterView.OnItemClickListener for example:

mAdapter.setOnItemClickListener((AdapterView.OnItemClickListener)this);

What if this class implements more than just AdapterView.OnItemClickListener but another interface? Would the above explicit cast then be necessary?

Answers


You don't need a cast in this case, because MainActivityFragment is lower in the hierarchy than the interface, so at compile time it is known that it implements OnItemClickListener.

You only need a cast if you only know at runtime that it implements that interface, for instance if you have a variable Fragment f that holds an object instance that was instantiated as a MainActivityFragment.

It is not a problem if the class implements multiple interfaces, because that doesn't introduce any ambiguity.


You don't need to cast because the method accepts a AdapterView.OnItemClickListener, and your MainActivityFragment is an AdapterView.OnItemClickListener.

When you say that a class/interface U extends or implements another class/interface T, then instances of U are also instances of T. The compiler will allow you to use a reference of type U wherever a reference of type T is accepted.

Imagine the alternative.

Human: A truck is an automobile.
Compiler: Cool.
Human: This method accepts an automobile and washes it.
Compiler: OK.
Human: Send this truck through that method.
Compiler: Whoa, there, Nelly! You didn't tell me *this* truck is an automobile!

What if this class implements more than just AdapterView.OnItemClickListener but another interface? Would the above explicit cast then be necessary?

No. If your MainActivityFragment implemented other interfaces, it would also be an instance of those interfaces, and no cast would be necessary.


Need Your Help

Split words with Tesseract tess-two on Android

java android tesseract tess-two

I try to use tesseract tess-two to read question and answears from images in android. At the moment I get a String with every word on the image.