How to create interface between Fragment and adapter? - java

I have fragment with ListView, say MyListFragment, and custom CursorAdapter.
I'm setting onClickListener in this adapter for the button in the list row.
public class MyListAdapter extends CursorAdapter {
public interface AdapterInterface {
public void buttonPressed();
}
...
#Override
public void bindView(final View view, final Context context, final Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
...
holder.button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// some action
// need to notify MyListFragment
}
});
}
}
public MyListFragment extends Fragment implements AdapterInterface {
#Override
public void buttonPressed() {
// some action
}
}
I need to notify fragment when the button is pressed. How to invoke this interface?
Help, please.

Make a new constructor and an instance variable:
AdapterInterface buttonListener;
public MyListAdapter (Context context, Cursor c, int flags, AdapterInterface buttonListener)
{
super(context,c,flags);
this.buttonListener = buttonListener;
}
When the Adapter is made, the instance variable will be given the proper reference to hold.
To call the Fragment from the click:
public void onClick(View v) {
buttonListener.buttonPressed();
}
When making the Adapter, you will have to also pass your Fragment off to the Adapter. For example
MyListAdapter adapter = new MyListAdapter (getActivity(), myCursor, myFlags, this);
since this will refer to your Fragment, which is now an AdapterInterface.
Keep in mind that on orientation of the Fragment changes, it will most likely be recreated. If your Adapter isn't recreated, it can potentially keep a reference to a nonexistent object, causing errors.

Using Eventbus:
Examples:
https://github.com/kaushikgopal/RxJava-Android-Samples/tree/master/app/src/main/java/com/morihacky/android/rxjava/rxbus
or
https://github.com/greenrobot/EventBus
Using Interfaces:
I understand the current answer but needed a more clear example. Here is an example of what I used with an Adapter(RecyclerView.Adapter) and a Fragment.
Create Callback Interface:
public interface AdapterCallback {
void onMethodCallback();
}
Passing in Callback/Fragment:
This will implement the interface that we have in our Adapter. In this example, it will be called when the user clicks on an item in the RecyclerView.
In your Fragment:
public class MyFragment extends Fragment implements AdapterCallback {
private MyAdapter mMyAdapter;
#Override
public void onMethodCallback() {
// do something
}
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mMyAdapter = new MyAdapter(this); // this class implements callback
}
}
Use the Callback in your Adapter:
In the Fragment, we initiated our Adapter and passed this as an argument to the constructer. This will initiate our interface for our callback method. You can see that we use our callback method for user clicks.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private AdapterCallback mAdapterCallback;
public MyAdapter(AdapterCallback callback) {
this.mAdapterCallback = callback;
}
#Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
// simple example, call interface here
// not complete
viewHolder.itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mAdapterCallback.onMethodCallback();
}
});
}
}
or Use the Fragment in your Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private AdapterCallback mAdapterCallback;
public MyAdapter(Fragment fragment) {
try {
this.mAdapterCallback = ((AdapterCallback) fragment);
} catch (ClassCastException e) {
throw new ClassCastException("Fragment must implement AdapterCallback.");
}
}
#Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
// simple example, call interface here
// not complete
viewHolder.itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
mAdapterCallback.onMethodCallback();
} catch (ClassCastException exception) {
// do something
}
}
});
}
}

Follow the 2 steps below for receive callback from Adapter in Fragment (or Activity)
First: In your Adapter
public class ListAdapter extends RecyclerView.Adapter < RecyclerListAdapter.ItemViewHolder > {
...
private ListAdapterListener mListener;
public interface ListAdapterListener { // create an interface
void onClickAtOKButton(int position); // create callback function
}
public RecyclerListAdapter(Context mContext, ArrayList < Items > listItems, ListAdapterListener mListener) { // add the interface to your adapter constructor
...
this.mListener = mListener; // receive mListener from Fragment (or Activity)
}
...
public void onBindViewHolder(final ItemViewHolder holder, final int position) {
holder.btnOK.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// use callback function in the place you want
mListener.onClickAtOKButton(position);
}
});
...
}
...
}
Second: In your Fragment (or Activity), there are 2 ways for implement callback method
Way 1
public MyListFragment extends Fragment {
...
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
...
ListAdapter adapter = new ListAdapter(getActivity(), listItems, new ListAdapter.ListAdapterListener() {
#Override
public void onClickAtOKButton(int position) {
Toast.makeText(getActivity(), "click ok button at" + position, Toast.LENGTH_SHORT).show();
}
});
...
}
}
Way 2
public MyListFragment extends Fragment implements ListAdapter.ListAdapterListener {
...
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
ListAdapter adapter = new ListAdapter (getActivity(), listItems, this);
...
}
#Override
public void onClickAtOKButton(int position) {
Toast.makeText(getActivity(), "click ok button at" + position, Toast.LENGTH_SHORT).show();
}
}

This is very similar to the way an activity and a fragment should communicate. In the constructor of your adapter, pass a reference of your fragment, cast it to your interface and just call yourReference.buttonPressed() on your onClick method.

a solution for NPE is first to make conctractor in your Fragment like that
public MyFragment MyFragment(){
return this;
}
then initialize your listener is adapter like that
Lisener lisener = new MyFragment();

Make a constructor like that:
public MyAdapter(Activity activity,AlertMessageBoxOk alertMessageBoxOk) {
this.mActivity = activity;
mAlertMessageBoxOk = alertMessageBoxOk;
}
call the interface from adapter use any event
mAlertMessageBoxOk.onOkClick(5);
after that implement AlertMessageBoxOk interface to your fragment like this,
class MyFragment extends Fragment implements AlertMessageBoxOk {
#Override
public void onOkClick(int resultCode) {
if(resultCode==5){
enter code here
}
}
}

Related

Passing data from RecyclerView to Fragment?

I am currently creating an application which consists of a Fragment, an Adapter for a RecyclerView and a RecyclerView which is accessed through the fragment. I need data to be passed from the RecyclerView back to the fragment however am unable to do so as the Fragment isn't identified through the Intent. When the user selects an item from the RecyclerView this item should be then passed through to the fragment. I have the RecyclerView using onBackPressed() in order to navigate back to the fragment which works fine, however no data seems to pass. Please see below what I currently have:
CustomAdapter.java
private OnItemClickListener mOnItemClickListener;
public interface OnItemClickListener{
public void onItemClick(View view, int position);
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
holder.text1.setText(String.valueOf(text1.get(position)));
holder.text2.setText(String.valueOf(text2.get(position)));
holder.text3.setText(String.valueOf(text3.get(position)));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mOnItemClickListener.onItemClick(v, holder.getAdapterPosition());
}
});
}
InputToFragment.java
#Override
public void onItemClick(View view, int position) {
// Need to pass data through to Fragment, however unable to do so as it's not identified
// within the Intent
onBackPressed();
}
});
Fragment.java
// Nothing related to Passing data within the Fragment
Its for your fragment
YourFragment : Fragment() {
OnItemClickListener listener = new OnItemClickListener(){
#Override
public void onItemClick(View view, int position){
//this called if item at adapter clicked
}
}
....
//whatever lifecycle you choose for initialize adapter
onCreateView(){
adapter = new YourAdapter(listener);
}
public interface OnItemClickListener{
public void onItemClick(View view, int position);
}
}
and this for your adapter
private OnItemClickListener listener;
YourConstructorAdapter(OnItemClickListener listener){
this.listener = listener;
}
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, int position) {
holder.text1.setText(String.valueOf(text1.get(position)));
holder.text2.setText(String.valueOf(text2.get(position)));
holder.text3.setText(String.valueOf(text3.get(position)));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// this code calling method from fragment
listener.onItemClick(v, position);
}
});
I'm highly recommend migrate to kotlin and use higher-order function, its very simple.
You can use interface, here is how to do it
create interface to handle click:-
public interface OnCustomItemSelectListener {
void onCustomItemSelected(String data);
}
not extend it in your fragment or activity:-
public class MyActivity implements OnCustomItemSelectListener {
#Override
public void onCustomItemSelected(String data) {
/*store it if neede */
/* additional code */
}
}
In recycler view pass this activity to recycler view constructor and inside your custom adapter you can assign this activity to listener interface and call the onCustomItemSelected method from overridden onClick(), which will be in your previous activity or fragment.
OnCustomItemSelectListener itemSelectListener;
public CustomAdapter(Activity listenerAct, .....){
this.itemSelectListener = listenerAct;
}
#Override
public void onClick(View view)
{
itemSelectListener.onCustomItemSelected(data);
}
this will pass data to onCustomItemSelected() method in your fragment/activity

Recycler Adapter callback nullpointer

i have recycler adapter like this
public class ShopUsersAdapter extends RecyclerView.Adapter<ShopUsersAdapter.MyViewHolder> implements View.OnClickListener {
private List<ShopUsersRecyclerModel> user_list;
private Context context;
private AdminCheckLocActivity activity;
private AdapterCallback mAdapterCallback;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView user;
public TextView type;
private ImageButton btn_loc;
public MyViewHolder(View view) {
super(view);
user = (TextView) view.findViewById(R.id.txt_text);
type =(TextView)view.findViewById(R.id.txt_count);
btn_loc=(ImageButton)view.findViewById(R.id.btn_loc);
}
}
#Override
public ShopUsersAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.map_pop_up_item, parent, false);
context=parent.getContext();
itemView.setOnClickListener(this);
return new ShopUsersAdapter.MyViewHolder(itemView);
}
#Override
public void onClick(View v) {
}
public ShopUsersAdapter(List<ShopUsersRecyclerModel> user_list, AdminCheckLocActivity activity) {
this.user_list = user_list;
this.activity=activity;
this.mAdapterCallback = ((AdapterCallback) context);
}
#Override
public void onBindViewHolder(final ShopUsersAdapter.MyViewHolder holder, int position) {
final ShopUsersRecyclerModel user = user_list.get(position);
holder.user.setText(user.getUser_info());
if (user.getUser_type()==3){holder.type.setText("TV Pro.");}
if (user.getUser_type()==4){holder.type.setText("B. Esya Pro.");}
holder.btn_loc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mAdapterCallback.onMethodCallback(user.getUser_info());
}
});
}
#Override
public int getItemCount() {
return user_list.size();
}
public interface AdapterCallback {
void onMethodCallback(String userName);
}
}
but i get error
NullPointer at
mAdapterCallback.onMethodCallback(user.getUser_info());
my activity code;
#Override
public void onMethodCallback(final String userName) {
Toast.makeText(this,userName,Toast.LENGTH_LONG).show();
}
and i implement this like ;
implements ShopUsersAdapter.AdapterCallback
userInfo data is not null, i check this. but i need this callback all of my recyclers please help me.
I suggest changing your adapter's constructor to directly receive a callback:
public ShopUsersAdapter(List<ShopUsersRecyclerModel> user_list, AdminCheckLocActivity activity, AdapterCallback callback) {
this.user_list = user_list;
this.activity=activity;
this.mAdapterCallback = callback;
}
You can also make sure your callback isn't null when you're utilizing it:
holder.btn_loc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// This should be optional for your case
// but it can be useful if you're ever in a situation
// where the callback isn't always available
if(mAdapterCallback != null){
mAdapterCallback.onMethodCallback(user.getUser_info());
}
}
});
And within your Activity, make sure to pass in the callback as an argument when you create your Adapter instance:
// Use 'this' since your Activity implements the callback
ShopUsersAdapter adapter = new ShopUsersAdapter(myList, myActivity, this);

Where should I call Interface in android?

I am trying to call the activity method from the adaptor class using interface.And both the activity are independent i.e. class which is calling adapter and the class where the method is defined.
Interface class
public interface AdapterCallback {
int onMethodCallback();
}
Adapter class
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {
String[] goals;
Context context;
private AdapterCallback mAdapterCallback;
public SimpleAdapter(Context context, String[] goals)
{
super();
this.context=context;
this.goals=goals;
}
/* public SimpleAdapter(Context context) {
try {
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement AdapterCallback.");
}
}*/
#Override
public SimpleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_item,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final SimpleAdapter.ViewHolder holder, int position) {
holder.textView.setText(goals[position]);
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
mAdapterCallback = ((AdapterCallback) context);
int result=mAdapterCallback.onMethodCallback();
Toast.makeText(context,Integer.toString(result), Toast.LENGTH_SHORT).show();
} catch (ClassCastException exception) {
// do something
Log.i("In the catch","Yes");
}
}
});
}
#Override
public int getItemCount() {
return goals.length;
}
public class ViewHolder extends RecyclerView.ViewHolder {
Button textView;
public ViewHolder(View itemView) {
super(itemView);
textView=(Button) itemView.findViewById(R.id.text);
}
}
}
Method is defined in the MainActivity.class
#Override
public int onMethodCallback() {
// do something
return 2;
}
Problem:
How should I call the interface function so that indirectly it will call the function defined in the MainActivity class.
I know I need to provide the context of the MainActivity as
mAdapterCallback = ((AdapterCallback) context);
but where should I put this code.
IF i put this code in the constructor then it will not get the MainActivity class context because adapter is calling from another class.
EDIT:
public class MainActivity extends AppCompatActivity implements AdapterCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public int onMethodCallback() {
// do something
return 2;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public int sampleFunction()
{
return 2;
}
}
EDIT 2
Class which is calling the adaptor class
public class OtherClass extends AppCompatActivity {
RecyclerView recyclerView;
SimpleAdapter simpleAdapter;
String[] action_name={"Swimming","Yoga","SWD","IFT","Follow Diet Plan", "Diagnostic Tests","Record Temperature","Record Blood Pressure"," Record Sugar Level","Record Weight"};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xtra);
recyclerView=(RecyclerView) findViewById(R.id.recylerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
simpleAdapter=new SimpleAdapter(this, action_name);
recyclerView.setAdapter(simpleAdapter);
}
}
First you have set the interface.Write a method like this in your adapter class
AdapterCallback adapterCallback ;
public void setAdapterCallback(AdapterCallback adapterCallback){
this.adapterCallback = adapterCallback
}
Now impliment and initialize the interface where you actually requires the callback. In your case MainActivity Do like this
MainActivity extends AppCompatActivity implements AdapterCallback
now initialize your interface like this.
SimpleAdapter adpter = new SimpleAdapter()
adpter.setAdapterCallback(this); // very imp step
Now send the callback like this
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(adapterCallback != null){
adapterCallback.onMethodCallback();
}
}
});
That's all you will get callback on your mainactivity..
Edit
I see you have your adapter set in another activity ..In that case you have to pass your interface object like this
AdapterCallback adapterCallback = this;
Intent intent = new Intent(context, OtherClass.class);
intent.putExtra("interface", adapterCallback);
startActivity(intent);
And retreive it in OtherClass;
Intent intent = getIntent();
AdapterCallback inter = (AdapterCallback) intent.getSerializableExtra("interface");
Also change interface to serializable .
public interface AdapterCallback extends Serializable {
int onMethodCallback();
}
And setInterface like this
simpleAdapter.setAdapterCallback(inter);
If you jsut used a fragment instead of otherclass it would have been a lot easier..
Edit
If both activities are independent then you can write a gettter and setter for your interface in Application class. Set the interface from mainActivity and get the callback in your adater..
write this in your Application class
AdapterCallback adapterCallback;
public AdapterCallback getAdapterCallback() {
return adapterCallback;
}
public void setAdapterCallback(AdapterCallback adapterCallback) {
this.adapterCallback = adapterCallback;
}
Write this in your Main
((YourApplication)getApplication()). setAdapterCallback(this);
And use this method in your click
((YourApplication) getApplication()).getAdapterCallback().onMethodCallback();
If you have implemented interface AdapterCallback in MainActivity then call constructor of SimpleAdapter with including a new paramenter of AdapterCallback Object. Try with these change. It may helps you
String[] goals;
Context context;
private AdapterCallback mAdapterCallback;
public SimpleAdapter(Context context, AdapterCallback adapterCallback, String[] goals){
super();
this.context=context;
this.adapterCallback = adapterCallback;
this.goals=goals;
}
and remove this
mAdapterCallback = ((AdapterCallback) context);
I'm not sure just a work around try,
If u have an Util class create a method or Create a Util class and do
say
private Context mContext;
public void setContext(Context context) {
mContext = context;
}
public Context getContext(){
return mContext;
}
Then
set the context in MainActivity
like
Util.setContext(MainActivity.this);
and in SimpleAdapter class use Util.getContext() and
Context context = Util.getContext();
if(context != null && context instanceof MainActivity){
mAdapterCallback = ((AdapterCallback) context);
int result=mAdapterCallback.onMethodCallback();
}
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {
String[] goals;
Context context;
private AdapterCallback mAdapterCallback;
public SimpleAdapter(Context context, String[] goals)
{
super();
this.context=context;
this.goals=goals;
}
/* public SimpleAdapter(Context context) {
try {
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement AdapterCallback.");
}
}*/
#Override
public SimpleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.simple_item,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final SimpleAdapter.ViewHolder holder, int position) {
holder.textView.setText(goals[position]);
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
mAdapterCallback = ((AdapterCallback) context);
int result=mAdapterCallback.onMethodCallback();
Toast.makeText(context,Integer.toString(result), Toast.LENGTH_SHORT).show();
} catch (ClassCastException exception) {
// do something
Log.i("In the catch","Yes");
}
}
});
}
#Override
public int getItemCount() {
return goals.length;
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
Button textView;
public ViewHolder(View itemView) {
super(itemView);
textView=(Button) itemView.findViewById(R.id.text);
//for entire cell
itemView.setOnClickListener(this);
//or only for button
textView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
/*
If your want clicked position you can use bellow code
*/
//int clicked_position = getAdapterPosition();
mAdapterCallback.onMethodCallback(clicked_position,goals[clicked_position]);
}
}
}
this is the way we have to use interface in android recyclerview
Edits
change your interface like bellow
public interface AdapterCallback {
void onMethodCallback(int position,String value);
}
and on your OtherClass.class like bellow
public class OtherClass extends AppCompatActivity implements AdapterCallback{
RecyclerView recyclerView;
SimpleAdapter simpleAdapter;
String[] action_name={"Swimming","Yoga","SWD","IFT","Follow Diet Plan", "Diagnostic Tests","Record Temperature","Record Blood Pressure"," Record Sugar Level","Record Weight"};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xtra);
recyclerView=(RecyclerView) findViewById(R.id.recylerview);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
simpleAdapter=new SimpleAdapter(this, action_name);
recyclerView.setAdapter(simpleAdapter);
}
#Override
public void onMethodCallback(int position, String value) {
System.out.println(value+" "+position);
//start activity intent here , now you have position as well as selected value
}
}

Interface value is always null

I am using custom recycler view and in adapter class i have implemented interface which is always null on button click. Here is my adapter class.
public class FeedListAdapter extends
RecyclerView.Adapter<AddtoCartHolder> {
private OnFeedItemClickListener onFeedItemClickListener;
public FeedListAdapter(Activity activity, ArrayList<CartItem> feedItems) {
this.activity = activity;
this.feedItems = feedItems;
this.filteredfeedItems = feedItems;
inflater = LayoutInflater.from(activity);
}
public void setOnFeedItemClickListener(OnFeedItemClickListener onFeedItemClickListener) {
this.onFeedItemClickListener = onFeedItemClickListener;
}
#Override
public AddtoCartHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.feed_item, parent, false);
AddtoCartHolder viewHolder = new AddtoCartHolder(v);
setupClickableViews(v, viewHolder);
return viewHolder;
}
#Override
public void onBindViewHolder(final AddtoCartHolder holder, int position) {
CartItem item = (CartItem) filteredfeedItems.get(position);
holder.price.setText((String.valueOf(item.getProductName()) + ""));
holder.location.setText((String.valueOf(item.getQuantity())) + "");
}
private void setupClickableViews(final View view, final AddtoCartHolder cellFeedViewHolder) {
cellFeedViewHolder.plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(onFeedItemClickListener !=null){
onFeedItemClickListener.onAddClick(v, cellFeedViewHolder.getAdapterPosition());
}
else{
Toast.makeText(activity, "Data is null", Toast.LENGTH_LONG).show();
}
}
});
}
public interface OnFeedItemClickListener {
void onAddClick(View v, int position);
}
#Override
public int getItemCount() {
return filteredfeedItems.size();
}
I am always getting null whenever clicking on button really down know why it is coming null...
Here is my fragment class which have implemented interface.
public class MyFragment extends Fragment implements FeedListAdapter.OnFeedItemClickListener{
// the method
#Override
public void onAddClick(View v, int position) {
// TODO Auto-generated method stub
Snackbar.make(clContent, "Product removed from cart!",
Snackbar.LENGTH_SHORT).show();
}
You must be instantiating a FeedListAdapter in your fragment correct buddy ???
Like using statement :
FeedListAdapter adapter = new FeedListAdapter(this.getActivity(),your_array_list)
After instantiating your adapter just call your adapter's setOnFeedItemClickListener with 'this' as argument :) That's all :)
adapter.setOnFeedItemClickListener(this)
Hope my answer helped you :) Happy coding buddy :)
By the looks of things your aren't setting your listener. Thus, onFeedItemClickListener is always null.
Also MyFragment isn't actually doing anything, you haven't inflated a view, overridden onCreateView(...), etc.
There's a few things that you could definitely change to improve your implementation. But to get your listener working:
Just get rid of MyFragment you don't appear to be using it properly.
Move your implements FeedListAdapter.OnFeedItemClickListener to your Activity. i.e. Make your Activity implement your OnFeedItemClickListener interface rather than MyFragment (which doesn't appear to be doing anything).
Make FeedListAdapter set the listener in its constructor:
public FeedListAdapter(Activity activity, ArrayList<CartItem> feedItems)
{
this.activity = activity;
// Assume we the activity implements OnFeedItemClickListener
setOnFeedItemClickListener((OnFeedItemClickListener)activity);
this.feedItems = feedItems;
this.filteredfeedItems = feedItems;
inflater = LayoutInflater.from(activity);
}
Please keep in mind that this is a pretty bad implementation and you can definitely improve on it but for the purpose of the question, it's sufficient.

Call a Fragment method from an Adapter

I have a method sendData() in my fragment. This method starts a new Activity. I want to call this method from my ArrayAdapter.
Here is my code:-
HomeFragment.java
stagAdaper = new StaggeredAdapter(myContext, android.R.layout.simple_list_item_1, getList);
mGridView.setAdapter(stagAdaper);
private void sendData(int position)
{
myDialog = new ProgressDialog(myContext).show(getActivity(), "Fetching news..", "Just a moment");
myDialog.getWindow().setContentView(R.layout.openarticlewaitprogress);
myDialog.getWindow().setTitle("Loading..");
myDialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
new NewsDetails(myDialog);
Intent nIntent = new Intent(getActivity(),Details.class);
String Body=getList.get(position).getBody();
newsIntent.putExtra("Body", Body);
startActivity(nIntent);
}
StaggeredAdapter.java
viewHolder.layGridLayout.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
//viewHolder.layGridLayout.setForeground(R.drawable.foreground_selector);
}
});
return convertView;
}
How can I do it?
Edit :
Here is what I would use now. Older, "easier" solutions are available below.
MyFragment extends Fragment implements CustomAdapter.EventListener {
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
CustomAdapter adapter = new CustomAdapter(..., this);
}
void onEvent(int data) {
doSomething(data);
}
}
CustomAdapter extends BaseAdapter {
EventListener listener;
public interface EventListener {
void onEvent(int data);
}
public CustomAdapter(..., EventListener listener) {
this.listener = listener;
}
...
}
Now from any place in the adapter we can call listener.onEvent(data); to trigger the method in the fragment.
Moreover, instead of providing a listener through the constructor, we can add another method in the adapter such as registerListener(EventListener eventListener) and then maintain a list of listeners if needed.
Old Answer:
Solution 1 :
Make the adapter an inner class of your fragment, so that you can call the method directly.
Solution 2 :
Update your adapter constructor to accept the Fragment as a parameter.
Something like :
customAdapter = new CustomAdapter(myContext, android.R.layout.simple_list_item_1, getList, HomeFragment.this);
and update the constructor of the Adapter :
public CustomAdapter(Context context, int id, HomeFragment fragment) {
this.fragment = fragment;
}
then you call methods using the fragment variable.
fragment.doSomething();
I know it's late to answer but There are 2 ways more to do it:
You can also send broadcast from adapter and register it in fragment.
Use interface. Refer this SO question for details.
You can make sendData method as static
public static void sendData(int position)
{
......
}
n call it as
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
HomeFragment.sendData(position)
........
}

Categories