You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Spinner加载REST API返回的Horario属性并关联ID问题

解决AsyncTask异步加载后Spinner无数据的问题

嘿,我一眼就看出问题所在了——你踩了异步编程里最经典的坑:在异步任务还没完成、数据还没返回的时候,就急着去遍历列表!AsyncTask的execute()方法是异步启动后台任务的,主线程会立刻继续执行后面的代码,这时候你的Horario列表肯定是空的,Spinner自然加载不到数据。

核心解决方案

把Spinner的初始化、数据填充逻辑,全部移到AsyncTask的onPostExecute()方法里。这个方法是后台任务完成后自动在主线程调用的,刚好适合更新UI,而且此时你已经拿到了完整的Horario列表。

修改后的代码示例

我帮你调整了FaltasActivity里的HorarioATask,重点优化了数据加载后的UI处理逻辑,同时帮你做好了选中时间后存储对应ID的准备:

public class FaltasActivity extends AppCompatActivity {
    private Spinner horarioSpinner;
    private int selectedHorarioId; // 用于存储选中的日程ID,提交缺勤请求用

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_faltas);
        
        horarioSpinner = findViewById(R.id.your_spinner_id); // 替换成你的Spinner ID
        
        // 启动异步任务获取日程数据
        new HorarioATask().execute();
    }

    private class HorarioATask extends AsyncTask<Void, Void, List<Horario>> {

        @Override
        protected List<Horario> doInBackground(Void... voids) {
            // 这里调用你的自研REST API获取Horario列表
            // 注意:处理好网络异常、解析异常,避免返回null
            try {
                return YourApiClient.getHorarios(selectedCourseId, selectedStudentId); // 替换成你的API调用逻辑,传入课程和学生参数
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onPostExecute(List<Horario> horarioList) {
            super.onPostExecute(horarioList);
            
            // 先判断数据是否有效
            if (horarioList == null || horarioList.isEmpty()) {
                Toast.makeText(FaltasActivity.this, "未获取到可用日程", Toast.LENGTH_SHORT).show();
                return;
            }

            // 准备Spinner显示的时间列表,以及时间和ID的映射关系
            List<String> inicioTimeList = new ArrayList<>();
            Map<String, Integer> timeToIdMap = new HashMap<>();
            
            for (Horario horario : horarioList) {
                String inicioTime = horario.getInicio();
                inicioTimeList.add(inicioTime);
                timeToIdMap.put(inicioTime, horario.getId()); // 绑定时间和对应ID
            }

            // 设置Spinner适配器
            ArrayAdapter<String> adapter = new ArrayAdapter<>(
                    FaltasActivity.this,
                    android.R.layout.simple_spinner_item,
                    inicioTimeList
            );
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            horarioSpinner.setAdapter(adapter);

            // 设置选中监听,获取对应ID
            horarioSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    String selectedTime = parent.getItemAtPosition(position).toString();
                    selectedHorarioId = timeToIdMap.get(selectedTime);
                    // 这里可以测试输出,确认ID是否正确
                    Log.d("FaltasActivity", "选中的日程ID:" + selectedHorarioId);
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {
                    // 可选:处理未选中的情况,比如默认设置第一个ID
                    if (!horarioList.isEmpty()) {
                        selectedHorarioId = horarioList.get(0).getId();
                    }
                }
            });
        }
    }
}

关键注意点

  1. 参数传递:如果你的API需要课程和学生的ID作为参数,可以在HorarioATask的构造方法里传入,比如:

    private class HorarioATask extends AsyncTask<Void, Void, List<Horario>> {
        private int courseId;
        private int studentId;
    
        public HorarioATask(int courseId, int studentId) {
            this.courseId = courseId;
            this.studentId = studentId;
        }
    
        // 在doInBackground里用这两个参数调用API
    }
    

    调用时就传参数:new HorarioATask(selectedCourseId, selectedStudentId).execute();

  2. 异常处理:在doInBackground里一定要捕获网络请求、JSON解析的异常,避免因为请求失败导致onPostExecute拿到null而崩溃。

  3. 替代方案(可选):如果是新项目,官方已经不推荐使用AsyncTask了,建议改用Kotlin协程或者Retrofit+LiveData,这些方案的异步逻辑更清晰,也更稳定。不过既然你已经用了AsyncTask,先解决当前问题是优先的。

内容的提问来源于stack exchange,提问作者Víctor Vanaclocha Cebrián

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:31:27