Android:从Adapter获取Spinner数据传递至Activity提交Retrofit请求
嘿,我之前在做RecyclerView适配器和表单提交的时候也遇到过一模一样的问题。这里有几个靠谱的解决方案,能帮你把Spinner的选择数据从Adapter传到MainActivity里,你可以根据自己的项目情况选:
方案一:接口回调(最常用的传统实现方式)
这种方式通过定义回调接口,让Activity实现接口并传递给Adapter,当Spinner选中项变化时,Adapter主动通知Activity更新数据。
步骤1:在Adapter中定义回调接口并持有实例
public class RoutePlanVisitChangeAdapter extends RecyclerView.Adapter<RoutePlanVisitChangeAdapter.RoutePlanVisitChangeView> { private List<Retailers> mList; private Context context; private String[] daysList = {"MON", "TUE", "WED", "THU", "FRI", "SAT"}; // 新增回调接口实例 private OnDayChangedListener mDayChangedListener; // 定义回调接口 public interface OnDayChangedListener { void onDayUpdated(int position, String newSelectedDay, Retailers originalRetailer); } // 修改构造方法,传入回调接口 public RoutePlanVisitChangeAdapter(List<Retailers> mList, Context context, OnDayChangedListener listener) { this.mList = mList; this.context = context; this.mDayChangedListener = listener; } // 省略其他已有方法... }
步骤2:给Spinner设置选中监听,触发回调
在onBindViewHolder里添加Spinner的选择监听,当用户选择新日期时,调用回调方法通知Activity:
@Override public void onBindViewHolder(RoutePlanVisitChangeView holder, int position) { Retailers routePlanVisitChange = mList.get(position); // 省略原有绑定逻辑... // 设置Spinner选中监听 holder.toDay.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { String selectedNewDay = newDayList[pos]; // 触发回调,把位置、新日期、原始数据传给Activity if (mDayChangedListener != null) { mDayChangedListener.onDayUpdated(position, selectedNewDay, routePlanVisitChange); } } @Override public void onNothingSelected(AdapterView<?> parent) { // 可选:处理未选中的情况 } }); }
步骤3:在MainActivity中实现回调接口,维护变更数据
让MainActivity实现刚才定义的接口,在回调方法里更新RoutePlanDayRequests列表:
public class MainActivity extends AppCompatActivity implements RoutePlanVisitChangeAdapter.OnDayChangedListener { private List<RoutePlanDayRequests> mChangedRequests = new ArrayList<>(); private RoutePlanVisitChangeAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initialLoadingServiceList(); submitChangeRequest.setOnClickListener(v -> updateServiceList()); } private void initialLoadingServiceList(){ // 省略加载初始数据逻辑... // 初始化Adapter时传入当前Activity(即回调实现类) mAdapter = new RoutePlanVisitChangeAdapter(retailers, this, this); mRecyclerView.setAdapter(mAdapter); // 初始化变更列表,默认填充原始数据 for (Retailers retailer : retailers) { RoutePlanDayRequests req = new RoutePlanDayRequests(); req.setOldDay(retailer.getRoutePlanDayOfWeek().toUpperCase()); req.setNewDay(retailer.getRoutePlanDayOfWeek().toUpperCase()); req.setStatus("unchanged"); mChangedRequests.add(req); } } // 实现回调方法 @Override public void onDayUpdated(int position, String newSelectedDay, Retailers originalRetailer) { // 更新对应位置的请求数据 RoutePlanDayRequests req = mChangedRequests.get(position); req.setNewDay(newSelectedDay); req.setStatus("changed"); // 根据业务设置状态 } private void updateServiceList() { // 过滤出真正有变更的项(可选,根据接口要求调整) List<RoutePlanDayRequests> filteredRequests = new ArrayList<>(); for (RoutePlanDayRequests req : mChangedRequests) { if (!req.getOldDay().equals(req.getNewDay())) { filteredRequests.add(req); } } // 调用Retrofit接口 RetrofitInstance.getInstance(this) .create(RoutePlanService.class) .getSaveRoutePlanDay(new SaveDayRequest(new RequestBody("", filteredRequests))); } }
方案二:在Adapter内维护变更数据,提供获取方法
这种方式更简单,直接在Adapter里保存每个Item的变更状态,Activity需要数据时直接调用Adapter的方法获取。
步骤1:在Adapter中添加变更数据列表和获取方法
public class RoutePlanVisitChangeAdapter extends RecyclerView.Adapter<RoutePlanVisitChangeAdapter.RoutePlanVisitChangeView> { private List<Retailers> mList; private Context context; private String[] daysList = {"MON", "TUE", "WED", "THU", "FRI", "SAT"}; // 新增:保存每个Item的变更数据 private List<RoutePlanDayRequests> mChangedRequests = new ArrayList<>(); public RoutePlanVisitChangeAdapter(List<Retailers> mList, Context context) { this.mList = mList; this.context = context; // 初始化变更列表 for (Retailers retailer : mList) { RoutePlanDayRequests req = new RoutePlanDayRequests(); req.setOldDay(retailer.getRoutePlanDayOfWeek().toUpperCase()); req.setNewDay(retailer.getRoutePlanDayOfWeek().toUpperCase()); req.setStatus("unchanged"); mChangedRequests.add(req); } } // 新增:提供获取变更数据的方法 public List<RoutePlanDayRequests> getChangedRequests() { // 可选:过滤未变更的项 List<RoutePlanDayRequests> filtered = new ArrayList<>(); for (RoutePlanDayRequests req : mChangedRequests) { if (!req.getOldDay().equals(req.getNewDay())) { req.setStatus("changed"); filtered.add(req); } } return filtered; } // 省略其他已有方法... }
步骤2:在Spinner选中时更新Adapter内的列表
@Override public void onBindViewHolder(RoutePlanVisitChangeView holder, int position) { Retailers routePlanVisitChange = mList.get(position); // 省略原有绑定逻辑... holder.toDay.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { String selectedNewDay = newDayList[pos]; // 更新Adapter内对应位置的变更数据 RoutePlanDayRequests req = mChangedRequests.get(position); req.setNewDay(selectedNewDay); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); }
步骤3:在MainActivity中直接调用Adapter方法获取数据
public class MainActivity extends AppCompatActivity { private RoutePlanVisitChangeAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initialLoadingServiceList(); submitChangeRequest.setOnClickListener(v -> updateServiceList()); } private void initialLoadingServiceList(){ // 省略加载初始数据逻辑... mAdapter = new RoutePlanVisitChangeAdapter(retailers, this); mRecyclerView.setAdapter(mAdapter); } private void updateServiceList() { // 直接从Adapter获取变更数据 List<RoutePlanDayRequests> request = mAdapter.getChangedRequests(); RetrofitInstance.getInstance(this) .create(RoutePlanService.class) .getSaveRoutePlanDay(new SaveDayRequest(new RequestBody("", request))); } }
方案三:使用LiveData(适合Jetpack架构项目)
如果你的项目用了Jetpack组件,用LiveData可以更优雅地解耦Adapter和Activity,自动观察数据变化。
步骤1:创建ViewModel持有数据
public class RoutePlanViewModel extends ViewModel { private MutableLiveData<List<RoutePlanDayRequests>> mChangedRequestsLiveData = new MutableLiveData<>(); private List<RoutePlanDayRequests> mRequestList = new ArrayList<>(); // 初始化数据 public void init(List<Retailers> retailers) { mRequestList.clear(); for (Retailers retailer : retailers) { RoutePlanDayRequests req = new RoutePlanDayRequests(); req.setOldDay(retailer.getRoutePlanDayOfWeek().toUpperCase()); req.setNewDay(retailer.getRoutePlanDayOfWeek().toUpperCase()); req.setStatus("unchanged"); mRequestList.add(req); } mChangedRequestsLiveData.setValue(mRequestList); } // 更新指定位置的日期 public void updateDay(int position, String newDay) { RoutePlanDayRequests req = mRequestList.get(position); req.setNewDay(newDay); mChangedRequestsLiveData.setValue(mRequestList); } // 对外提供LiveData观察 public LiveData<List<RoutePlanDayRequests>> getChangedRequests() { return mChangedRequestsLiveData; } }
步骤2:Adapter中持有ViewModel,更新数据
public class RoutePlanVisitChangeAdapter extends RecyclerView.Adapter<RoutePlanVisitChangeAdapter.RoutePlanVisitChangeView> { private List<Retailers> mList; private Context context; private String[] daysList = {"MON", "TUE", "WED", "THU", "FRI", "SAT"}; private RoutePlanViewModel mViewModel; public RoutePlanVisitChangeAdapter(List<Retailers> mList, Context context, RoutePlanViewModel viewModel) { this.mList = mList; this.context = context; this.mViewModel = viewModel; } @Override public void onBindViewHolder(RoutePlanVisitChangeView holder, int position) { Retailers routePlanVisitChange = mList.get(position); // 省略原有绑定逻辑... holder.toDay.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { String selectedNewDay = newDayList[pos]; // 通知ViewModel更新数据 mViewModel.updateDay(position, selectedNewDay); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } // 省略其他已有方法... }
步骤3:MainActivity中观察LiveData
public class MainActivity extends AppCompatActivity { private RoutePlanViewModel mViewModel; private List<RoutePlanDayRequests> mChangedRequests; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 获取ViewModel实例 mViewModel = new ViewModelProvider(this).get(RoutePlanViewModel.class); initialLoadingServiceList(); // 观察数据变化 mViewModel.getChangedRequests().observe(this, requests -> { mChangedRequests = requests; }); submitChangeRequest.setOnClickListener(v -> updateServiceList()); } private void initialLoadingServiceList(){ // 省略加载初始数据逻辑... mViewModel.init(retailers); RoutePlanVisitChangeAdapter adapter = new RoutePlanVisitChangeAdapter(retailers, this, mViewModel); mRecyclerView.setAdapter(adapter); } private void updateServiceList() { // 过滤变更项 List<RoutePlanDayRequests> filtered = new ArrayList<>(); for (RoutePlanDayRequests req : mChangedRequests) { if (!req.getOldDay().equals(req.getNewDay())) { req.setStatus("changed"); filtered.add(req); } } // 调用Retrofit接口 RetrofitInstance.getInstance(this) .create(RoutePlanService.class) .getSaveRoutePlanDay(new SaveDayRequest(new RequestBody("", filtered))); } }
内容的提问来源于stack exchange,提问作者Shiv
相关产品推荐
相关产品推荐

