[英]How to create interface between Fragment and adapter?
I have fragment with ListView
, say MyListFragment
, and custom CursorAdapter
.我有ListView
片段,比如MyListFragment
和自定义CursorAdapter
。 I'm setting onClickListener
in this adapter for the button in the list row.我在此适配器中为列表行中的按钮设置onClickListener
。
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. 制作Adapter
,您还必须将片段传递给适配器。 For example 例如
MyListAdapter adapter = new MyListAdapter (getActivity(), myCursor, myFlags, this);
since this
will refer to your Fragment, which is now an AdapterInterface
. 因为this
将引用你的Fragment,它现在是一个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. 如果未重新创建适配器,则可能会保留对不存在的对象的引用,从而导致错误。
Examples: 例子:
https://github.com/kaushikgopal/RxJava-Android-Samples/tree/master/app/src/main/java/com/morihacky/android/rxjava/rxbus https://github.com/kaushikgopal/RxJava-Android-Samples/tree/master/app/src/main/java/com/morihacky/android/rxjava/rxbus
or 要么
https://github.com/greenrobot/EventBus https://github.com/greenrobot/EventBus
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
. 以下是我使用Adapter
(RecyclerView.Adapter)和Fragment
的示例。
Create Callback
Interface: 创建Callback
接口:
public interface AdapterCallback {
void onMethodCallback();
}
Passing in Callback
/ Fragment
: 传入Callback
/ Fragment
:
This will implement the interface
that we have in our Adapter
. 这将实现interface
,我们在我们的Adapter
。 In this example, it will be called when the user clicks on an item in the RecyclerView
. 在此示例中,将在用户单击RecyclerView
的项目时调用它。
In your Fragment
: 在你的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: 使用适配器中的Callback
:
In the Fragment
, we initiated our Adapter
and passed this as an argument to the constructer. 在Fragment
,我们启动了我们的Adapter
并将其作为参数传递给constructer。 This will initiate our interface
for our callback method. 这将启动我们的回调方法interface
。 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: 或使用适配器中的Fragment
:
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)
按照以下2个步骤接收来自Fragment (or Activity)
Adapter
回调
First: In your Adapter
第一:在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 第二:在Fragment (or Activity)
,有两种实现回调方法的方法
Way 1 方式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 方式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. 在适配器的构造函数中,传递片段的引用,将其强制转换为接口,然后在onClick方法上调用yourReference.buttonPressed()。
a solution for NPE is first to make conctractor in your Fragment like that NPE的解决方案是首先在你的Fragment中制作这样的conctractor
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, 之后,像你这样实现AlertMessageBoxOk接口到你的片段,
class MyFragment extends Fragment implements AlertMessageBoxOk {
@Override
public void onOkClick(int resultCode) {
if(resultCode==5){
enter code here
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.