学而实习之 不亦乐乎

Android:在RecyclerViewr的adapter中调用Activity或Fragment中的方法

2021-11-03 16:11:46

当我们在 Activity 或者 Fragment 中使用 RecyclerView 时,如果想在 Adapter 中访问 Activity 或者 Fragment 中的方法,其实很简单,使用一个内部类的 Adapter 就可以了。但如果提供的 Adapter 不是内部类呢?可以用下面的方法:

1.广播
2.接口回调

当然,这里只是举例,其实在 Android 中这两种方式还能满足更多的情况。

一、使用广播

这里使用本地广播实现的上面的问题。具体实现如下:

1.新建一个Adapter继承自RecyclerView.Adapter,如下:

public class ProvinceCityAdapter extends
        RecyclerView.Adapter<ProvinceCityAdapter.ViewHolder> {
    private static final String TAG = "ProvinceCityAdapter";
    private List<String> mDataList = new ArrayList<>();   //数据
    private LocalBroadcastManager localBroadcastManager;
    //用于缓存数据
    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        //构造方法
        public ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv_prcico);
        }
    }
    public ProvinceCityAdapter(List<String> mDataList) {
        this.mDataList = mDataList;
    }
    //创建ViewHolder实例
    @Override
    public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
        final View view = LayoutInflater.from(parent.getContext()).
                inflate(R.layout.item_prcico_layout, parent, false);
        final ViewHolder viewHolder = new ViewHolder(view);
        localBroadcastManager = LocalBroadcastManager.getInstance(parent.getContext());
        final Intent intent = new Intent(ChooseAreaFragment.LOCAL_BROADCAST);
        viewHolder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int adapterPosition = viewHolder.getAdapterPosition();  //可以获取到点击的索引
                intent.putExtra("city", viewHolder.textView.getText().toString());     //通知fragment,让它去调用queryCity()方法
                localBroadcastManager.sendBroadcast(intent);               //发送本地广播通知fragment该刷新了
            }
        });
        return viewHolder;
    }
    
    //子项数据进行赋值   当滚动到屏幕内时执行
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String position_choice = mDataList.get(position);
        holder.textView.setText(position_choice);
    }
    
    //多少个子项
    @Override
    public int getItemCount() {
        return mDataList.size();
    }
}

2.注册本地广播,用以接收到 adapter 发送的广播,如下:

public class ChooseAreaFragment extends Fragment {
    private static final String TAG = "ChooseAreaFragment";
    private RecyclerView recyclerView;  //列表
    private ProvinceCityAdapter adapter;  //适配器
    private List<String> dataList = new ArrayList<>();   //数据
    private IntentFilter intentFilter;
    private LocalReceiver localReceiver;    //本地广播接收者
    private LocalBroadcastManager localBroadcastManager;   //本地广播管理者可以用来注册广播
    /**
     * 发送本地广播的action
     */
    public static final String LOCAL_BROADCAST = "com.xfhy.casualweather.LOCAL_BROADCAST";
    //做一些初始化操作
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.choose_area, container, false);
        recyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);
        
        //获取LocalBroadcastManager   本地广播管理者实例
        localBroadcastManager = LocalBroadcastManager.getInstance(getContext());
        localReceiver = new LocalReceiver();
        intentFilter = new IntentFilter();
        intentFilter.addAction(LOCAL_BROADCAST);   //添加action
        localBroadcastManager.registerReceiver(localReceiver,intentFilter);   //注册本地广播
        //设置LayoutManager
        LinearLayoutManager linearManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(linearManager);
        //设置adapter
        adapter = new ProvinceCityAdapter(dataList);
        recyclerView.setAdapter(adapter);
        return view;
    }

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

    /**
     * 查询选中省内所有的市,优先从数据库查询,如果没有查询到再去服务器查询
     */
    protected void showCities(String city) {
        Log.i(TAG, "Select Cities: "+ city);
    }

    private class LocalReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(!action.equals(LOCAL_BROADCAST)){
                return ;
            }

            String city = intent.getBooleanExtra("city",false);  //判断是否需要调用查询城市
            showCities(city);
        }
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);    //取消广播的注册
    }
}

二、回调接口

1.在 Adapter 中写一个接口

public interface ItemListener {
    public void onItemClick(String city);
}

2.在 Adapter 中定义一个属性,ItemListener mItemListener,并写如下方法:

public void setOnItemClickListener (ItemListener  ItemListener) {
    this.mItemListener = ItemListener;
}

这就完成了监听器的初始化,只需要在 Adapter 中的处理点击的事件的地方,调用一下 mItemListener.onItemClick() 即可.即可回调。

3.在 Activity 或 fragment 中,当 Adapter 接收到点击事件时,回调该接口,即可在这里接收到消息。

adapter.setOnItemClickListener (new ItemListener(){
    @Override
    public void onItemClick(String city){
    }
});

完成上面的工作,fragment即完成了和adapter通信的任务。