如何在Fragment和适配器之间创建接口?

时间:2013-03-16 00:59:15

标签: java android interface

我有ListView的片段,比如MyListFragment和自定义CursorAdapter。 我在此适配器中为列表行中的按钮设置了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
    }
}

我需要在按下按钮时通知片段。如何调用此界面?

请帮助。

6 个答案:

答案 0 :(得分:71)

创建一个新的构造函数和一个实例变量:

AdapterInterface buttonListener;

public MyListAdapter (Context context, Cursor c, int flags, AdapterInterface buttonListener)
{
  super(context,c,flags);
  this.buttonListener = buttonListener;
}

制作适配器时,实例变量将被赋予适当的保持参考。

从点击中调用片段:

public void onClick(View v) {
   buttonListener.buttonPressed();
}

制作Adapter时,您还必须将片段传递给适配器。例如

MyListAdapter adapter = new MyListAdapter (getActivity(), myCursor, myFlags, this);

因为this会引用您的片段,现在是AdapterInterface

请记住,在片段方向更改时,很可能会重新创建。如果未重新创建适配器,则可能会保留对不存在的对象的引用,从而导致错误。

答案 1 :(得分:61)

使用Eventbus:

示例:

https://github.com/kaushikgopal/RxJava-Android-Samples/tree/master/app/src/main/java/com/morihacky/android/rxjava/rxbus

https://github.com/greenrobot/EventBus

使用接口:

我理解当前的答案,但需要一个更清晰的例子。以下是我与Adapter(RecyclerView.Adapter)和Fragment一起使用的示例。

创建Callback界面:

public interface AdapterCallback {
    void onMethodCallback();
}

传入Callback / Fragment

这将实现我们interface中的Adapter。在此示例中,当用户点击RecyclerView中的项目时会调用它。

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
    }
}

使用适配器中的Callback

Fragment中,我们启动了Adapter并将其作为参数传递给构造函数。这将为我们的回调方法启动interface。您可以看到我们使用回调方法进行用户点击。

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();
            }
        });
    }
}

或使用适配器中的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
                }
            }
        });
    }
}

答案 2 :(得分:27)

按照以下两个步骤接收来自Adapter

Fragment (or Activity)的回调

首先:在您的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);
            }
        });
        ...
    }
    ...
}

第二:在您的Fragment (or Activity)中,有两种实现回调方法的方法

方式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();
             }
         });
         ...
     }
 }

方式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();     
    }          
}

答案 3 :(得分:0)

这与活动和片段的通信方式非常相似。在适配器的构造函数中,传递片段的引用,将其强制转换为接口,然后在onClick方法上调用yourReference.buttonPressed()。

答案 4 :(得分:0)

NPE的解决方案是首先在你的片段中制作conctractor

Lisener lisener = new MyFragment();

然后初始化你的监听器是那样的适配器

.bashrc

答案 5 :(得分:0)

制作一个像这样的构造函数:

  public MyAdapter(Activity activity,AlertMessageBoxOk alertMessageBoxOk) {

  this.mActivity = activity;

  mAlertMessageBoxOk = alertMessageBoxOk;

}

从适配器调用接口使用任何事件

mAlertMessageBoxOk.onOkClick(5);

之后实现AlertMessageBoxOk接口到你的片段,

class MyFragment extends Fragment implements AlertMessageBoxOk {

@Override
public void onOkClick(int resultCode) {

  if(resultCode==5){

  enter code here 

      }
    } 
 }