Android用Volley传数组至服务器时首元素值变为0的解决办法
Android Volley提交ArrayList到服务器时首个元素值异常为0的问题
问题概述
在Android开发中,使用Volley发起POST请求向服务器提交包含sr_id和admission_id的ArrayList数据。Android端日志显示数组内所有数值均正确,但服务器端接收时,仅第一个元素的值被设为0。使用Postman调用同一API则无此异常。
相关截图说明
- 服务器端数据:接收的列表中第一个元素值为0,其余元素正常
- Android端数据:本地日志输出的数组内所有元素值均符合预期
- 请求参数日志:显示Android端构造的参数格式与Postman提交的格式存在差异
核心代码
public class AttendenceShowStdList extends AppCompatActivity { ActivityAttendenceShowStdListBinding AttendenceShowStdList; ArrayList<AttStdListModel> userlist = new ArrayList<>(); ArrayList<AllStdListsrIdAdmIdModel> list= new ArrayList<>(); ArrayList<AllStdListModel> stdlist = new ArrayList<>(); AttStdListAdapter adapter; private DatePickerDialog datePickerDialog; private String date,clid,sectionId,yrId,instId,usid,usType,attdate; SharedPreferences sharedPreferences_teach;//staff shareprefferece for profile fetch private static final String SHARED_PREF_NAME_TEACH="myprefteach"; private static final String Key_USID_TEACH = "techusid"; private static final String Key_INSTID_TEACH = "techinstid"; private static final String Key_USTYPE_TEACH = "techustype"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AttendenceShowStdList= ActivityAttendenceShowStdListBinding.inflate(getLayoutInflater()); setContentView(AttendenceShowStdList.getRoot()); sharedPreferences_teach =getSharedPreferences(SHARED_PREF_NAME_TEACH, Context.MODE_PRIVATE); instId=sharedPreferences_teach.getString(Key_INSTID_TEACH,null); usid=sharedPreferences_teach.getString(Key_USID_TEACH,null); usType=sharedPreferences_teach.getString(Key_USTYPE_TEACH,null); //getting data from TakeAttendenceAdapter cardview clid=getIntent().getExtras().getString("ClassId"); sectionId=getIntent().getExtras().getString("sectionId"); Log.d("cliddd",clid); yrId=getIntent().getExtras().getString("YearId"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); date = sdf.format(new Date()); Log.d("dttt",date); userlist = (ArrayList<AttStdListModel>) getModel(false); adapter = new AttStdListAdapter(this,userlist); AttendenceShowStdList.rvstdlist.setAdapter(adapter); AttendenceShowStdList.rvstdlist.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false)); getData(); //toolbar setSupportActionBar(AttendenceShowStdList.toolbar); Objects.requireNonNull(getSupportActionBar()).setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); AttendenceShowStdList.submit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { submitAttendence(); } }); } private List<AttStdListModel> getModel(boolean isSelect){ List<AttStdListModel> list = new ArrayList<>(); for(int i = 0; i < list.size(); i++){ AttStdListModel model = new AttStdListModel(); model.setSelected(isSelect); model.setAdmi_id(String.valueOf(list.get(i))); list.add(model); } return list; } private void getData() { RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); String url1="https://comzent.in/wonderschoolerp/apis/teacher/get_studteachers_att.php"; StringRequest request = new StringRequest(Request.Method.POST, url1, new com.android.volley.Response.Listener<String>() { @SuppressLint("NotifyDataSetChanged") @Override public void onResponse(String response) { try { JSONObject respObj = new JSONObject(response); JSONArray jsonArray5=respObj.getJSONArray("studatt_details"); Log.d("std details",jsonArray5.toString()); for(int i=0;i<jsonArray5.length();i++){ JSONObject jsonObject=jsonArray5.getJSONObject(i); String sr_id=jsonObject.optString("sr_id"); String admi_id=jsonObject.optString("admi_id"); String stud_name=jsonObject.optString("stud_name"); String stud_phone=jsonObject.optString("stud_phone"); String stud_email=jsonObject.optString("stud_email"); String attd_status=jsonObject.optString("attd_status"); String attd_reason=jsonObject.optString("attd_reason"); userlist.add(new AttStdListModel(sr_id,admi_id,stud_name,stud_phone,stud_email, attd_status,attd_reason)); Log.d("s", String.valueOf(userlist)); list.add(new AllStdListsrIdAdmIdModel(sr_id,admi_id,stud_name,stud_phone,stud_email, attd_status,attd_reason)); } } catch (JSONException e) { e.printStackTrace(); } adapter=new AttStdListAdapter(getApplicationContext(),userlist); AttendenceShowStdList.rvstdlist.setAdapter(adapter); adapter.notifyDataSetChanged(); } }, new com.android.volley.Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(getApplicationContext(), "Fail to get response = " + error, Toast.LENGTH_SHORT).show(); } }) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<String, String>(); params.put("get_studattd","1"); params.put("us_id",usid); params.put("inst_id",instId); params.put("class_id",clid); params.put("sec_id",sectionId); params.put("ay_id",yrId); params.put("stud_attend_date",date); return params; } }; queue.add(request); } //submit attendence private void submitAttendence() { RequestQueue queue = Volley.newRequestQueue(getApplicationContext()); String url1="https://comzent.in/wonderschoolerp/apis/teacher/take_studteacher_att.php"; StringRequest request = new StringRequest(Request.Method.POST, url1, new com.android.volley.Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject respObj = new JSONObject(response); String msg=respObj.getString("message"); Toast.makeText(AttendenceShowStdList.this, msg, Toast.LENGTH_LONG).show(); Log.d("response msg",msg); if(msg.equals("Attendance Generated Successfully..!")){ finish(); } } catch (JSONException e) { e.printStackTrace(); } } }, new com.android.volley.Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(getApplicationContext(), "Fail to get response = " + error, Toast.LENGTH_LONG).show(); Log.d("error msg", String.valueOf(error)); } }) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<String, String>(); ArrayList<String> allstdsrid = new ArrayList<String>(); for(int i=0; i < list.size(); i++) { allstdsrid.add(String.valueOf(list.get(i).getSr_id())); } params.put("sr_id", String.valueOf(allstdsrid)); Log.d("params", String.valueOf(params)); Log.d("allstudentsrid", String.valueOf(allstdsrid)); ArrayList<String> allstdadmid = new ArrayList<String>(); for(int i=0; i < list.size(); i++) { allstdadmid.add(list.get(i).getAdmi_id()); params.put("admission_id", String.valueOf(allstdadmid)); } Log.d("allstudentsadmid", String.valueOf(allstdadmid)); ///selected student list ArrayList<String> attstd = new ArrayList<String>(); for (int i = 0; i < AttStdListAdapter.userlist.size(); i++) { if (AttStdListAdapter.userlist.get(i).getSelected()) { attstd.add(AttStdListAdapter.userlist.get(i).getAdmi_id()); } } params.put("student_attend_submit","1"); params.put("class_id",clid); params.put("sec_id",sectionId); params.put("ay_id",yrId); params.put("att_status", String.valueOf(attstd)); Log.d("params", String.valueOf(params)); params.put("stud_attend_date",date); params.put("inst_id",instId); params.put("us_id",usid); params.put("us_type",usType); return params; } }; queue.add(request); } //toolbar back to home public boolean onOptionsItemSelected(@NonNull MenuItem item) { if(item.getItemId()==android.R.id.home){ finish(); } return super.onOptionsItemSelected(item); } }
问题原因分析
- 参数格式错误:代码中直接将
ArrayList通过String.valueOf()转为字符串(格式类似[123,456,789]),服务器端无法正确解析这种格式的字符串为数组,导致解析异常,首个元素被设为0。 - 重复覆盖参数:处理
admission_id时,在循环内部重复调用params.put("admission_id", ...),每次循环都会覆盖同一个key的值,最终仅保留最后一次循环生成的数组字符串,进一步加剧了解析问题。
解决方案
方案1:按表单数组格式提交参数
如果服务器端期望接收表单数组(如PHP后端的$_POST['sr_id']数组格式),需逐个添加数组元素,使用key[]作为参数名:
@Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<String, String>(); // 提交sr_id数组 for(int i=0; i < list.size(); i++) { params.put("sr_id[]", list.get(i).getSr_id()); } // 提交admission_id数组 for(int i=0; i < list.size(); i++) { params.put("admission_id[]", list.get(i).getAdmi_id()); } // 提交att_status数组 for(String admId : attstd) { params.put("att_status[]", admId); } // 其他固定参数 params.put("student_attend_submit","1"); params.put("class_id",clid); params.put("sec_id",sectionId); params.put("ay_id",yrId); params.put("stud_attend_date",date); params.put("inst_id",instId); params.put("us_id",usid); params.put("us_type",usType); return params; }
方案2:将数组序列化为JSON字符串提交
如果服务器端支持解析JSON格式参数,可将数组转为JSON字符串后提交:
- 先引入Gson依赖(或使用原生
JSONArray):
implementation 'com.google.code.gson:gson:2.10.1'
- 修改参数构造逻辑:
@Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<String, String>(); Gson gson = new Gson(); ArrayList<String> allstdsrid = new ArrayList<String>(); for(int i=0; i < list.size(); i++) { allstdsrid.add(list.get(i).getSr_id()); } params.put("sr_id", gson.toJson(allstdsrid)); ArrayList<String> allstdadmid = new ArrayList<String>(); for(int i=0; i < list.size(); i++) { allstdadmid.add(list.get(i).getAdmi_id()); } params.put("admission_id", gson.toJson(allstdadmid)); ArrayList<String> attstd = new ArrayList<String>(); for (int i = 0; i < AttStdListAdapter.userlist.size(); i++) { if (AttStdListAdapter.userlist.get(i).getSelected()) { attstd.add(AttStdListAdapter.userlist.get(i).getAdmi_id()); } } params.put("att_status", gson.toJson(attstd)); // 其他固定参数 params.put("student_attend_submit","1"); params.put("class_id",clid); params.put("sec_id",sectionId); params.put("ay_id",yrId); params.put("stud_attend_date",date); params.put("inst_id",instId); params.put("us_id",usid); params.put("us_type",usType); return params; }
同时服务器端需要对应修改,将接收的字符串反序列化为数组处理。
内容的提问来源于stack exchange,提问作者Unnati Sovitkar
相关产品推荐
相关产品推荐

