为嵌套 RecyclerView 设置 Volley
Setting Volley for Nested RecyclerView
我想做的是一个蛋糕店的菜单列表,菜单有3个类别,每个类别有不同的菜单.
所以我已经有一个嵌套的 RecyclerView,我的问题是当我想将 RecyclerView 与数据库连接时。我可以在片段中轻松地为父 RecyclerView 创建 Volley,但是很难为子 RecyclerView 创建 StringRequest 方法,因为我必须在 parent RecyclerView 的适配器.[=15= 中设置它]
更新
我缩小了我的问题范围,我已经知道如何在父级适配器中创建方法。现在我的子 RecyclerView StringRequest 有另一个问题。
根据我看到的教程 here,要用不同的菜单填充每个类别,我必须这样做:
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
ParentModel currentItem = parentModelArrayList.get(position);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(cxt, LinearLayoutManager.HORIZONTAL, false);
holder.childRecyclerView.setLayoutManager(layoutManager);
holder.childRecyclerView.setHasFixedSize(true);
holder.category.setText(currentItem.movieCategory());
ArrayList<ChildModel> arrayList = new ArrayList<>();
// added the first child row
if (parentModelArrayList.get(position).movieCategory().equals("Category1")) {
arrayList.add(new ChildModel(R.drawable.themartian,"Movie Name"));
arrayList.add(new ChildModel(R.drawable.moana,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.mov2,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.blackp,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi2,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood1,"Movie Name"));
}
// added in second child row
if (parentModelArrayList.get(position).movieCategory().equals("Category2")) {
arrayList.add(new ChildModel(R.drawable.moviedubbedinhindi2,"Movie Name"));
arrayList.add(new ChildModel(R.drawable.moviedubbedinhindi3,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi1,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi4,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi5,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi6,"Movie Name"));
}
// added in third child row
if (parentModelArrayList.get(position).movieCategory().equals("Category3")) {
arrayList.add(new ChildModel(R.drawable.hollywood6,"Movie Name"));
arrayList.add(new ChildModel(R.drawable.hollywood5,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood4,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood3,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood2,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood1,"Movie Name"));
}
ChildRecyclerViewAdapter childRecyclerViewAdapter = new ChildRecyclerViewAdapter(arrayList,holder.childRecyclerView.getContext());
holder.childRecyclerView.setAdapter(childRecyclerViewAdapter);
}
我自己尝试时成功了,但是当我尝试使用 Volley 获取数据时,我总是遇到问题,大多数时候问题是 StringRequest 使用相同的数据。所以我的问题是 如何使用 Volley 做同样的事情?
更新 2
今天我尝试使用我从其他 post 那里学到的 VolleyCallback 接口获取 StringRequest 中的值,首先我想通过只获取 name 值并将其传递给 onBindViewHolder。不幸的是,它失败了,虽然 ViewHolder 中的变量正确接收了值,但 onBindViewHolder 中的变量 returns null
这是界面:
public interface VolleyCallback {
void onSuccess(String result);
}
这是ViewHolder里面的方法class :
public void loadChildMenu(int categoryId, final VolleyCallback callback) {
RequestQueue requestQueue = Volley.newRequestQueue(context);
StringRequest stringRequest = new StringRequest(Request.Method.POST, Servers.VIEW_TRANSC_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("Response", response);
try {
JSONObject obj = new JSONObject(response);
JSONArray jArray = obj.getJSONArray("result");
for (int i = 0; i < jArray.length(); i++) {
JSONObject jObj = jArray.getJSONObject(i);
name = jObj.getString("name");
Log.e("TAG", "Name = " + name);
ModelTransaksi modelTransaksi = new ModelTransaksi();
modelTransaksi.setId(jObj.getInt("idmenu"));
modelTransaksi.setName(jObj.getString("name"));
modelTransaksi.setImage(jObj.getString("image"));
modelTransaksi.setPrice1(jObj.getInt("price1"));
modelTransaksi.setPrice2(jObj.getInt("price2"));
modelTransaksi.setSize(!jObj.getString("size").equals("0"));
dataChild.add(modelTransaksi);
}
callback.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("TAG", "Error : " + error.getMessage());
Toast.makeText(context, error.getMessage(), Toast.LENGTH_LONG).show();
}
}) {
@Nullable
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("idcat", String.valueOf(categoryId));
return params;
}
};
requestQueue.add(stringRequest);
}
这就是我在 onBindViewHolder 中调用它的方式:
//Add first child row
if (dataList.get(position).getIdCategory() == 1) {
holder.loadChildMenu(1, new VolleyCallback() {
@Override
public void onSuccess(String result) {
name = result;
}
});
Log.e("TAG2", "Name2 = " + name);
dataChild.add(new ModelTransaksi(name, 1000, 2000, "kacang.png"));
}
折腾了一周,终于找到办法了
我的解决方案的关键是使用一个 StringRequest 来填充 parent 和 child 适配器。首先,我所做的是使用一个 php 文件获取 parent 和 child 的数据,我就是这样做的:
<?php
include_once("../koneksi.php");
$sql = "SELECT * FROM menu";
$sql2 = "SELECT * FROM menu_category";
$query = mysqli_query($con, $sql);
$query2 = mysqli_query($con, $sql2);
$result = array();
$result2 = array();
while($row = mysqli_fetch_array($query)) {
array_push($result, array(
"idmenu"=>$row['id_menu'],
"category"=>$row['id_category'],
"name"=>$row['menu_name'],
"image"=>$row['menu_image'],
"size"=>$row['menu_size'],
"price1"=>$row['price1'],
"price2"=>$row['price2']
));
}
while($row2 = mysqli_fetch_array($query2)) {
array_push($result2, array(
"category"=>$row2['id_category'],
"catname"=>$row2['cat_name'],
));
}
echo json_encode(array('result'=>$result, 'result2'=>$result2));
mysqli_close($con);
?>
然后在StringRequest中,一次获取所有数据。我就是这样做的:
private void loadCategory() {
RequestQueue requestQueue = Volley.newRequestQueue(getContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, Servers.VIEW_TRANSC_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
//Get parent's data
JSONObject obj = new JSONObject(response);
JSONArray jArray = obj.getJSONArray("result2");
Log.d("response", String.valueOf(jArray));
for (int i = 0; i < jArray.length(); i++) {
JSONObject jObj = jArray.getJSONObject(i);
ModelTransaksiParent parentModel = new ModelTransaksiParent();
parentModel.setIdCategory(jObj.getInt("category"));
parentModel.setTransaksiCategory(jObj.getString("catname"));
//Get child data
JSONObject childObj = new JSONObject(response);
JSONArray childArray = childObj.getJSONArray("result");
ArrayList<ModelTransaksi> childList = new ArrayList<>();
for (int j=0; j < childArray.length(); j++) {
JSONObject cObj = childArray.getJSONObject(j);
if (jObj.getInt("category") == cObj.getInt("category")) {
childList.add(new ModelTransaksi(cObj.getString("name"), cObj.getInt("price1"), cObj.getInt("price2"), cObj.getString("image")));
}
}
parentModel.setDataChild(childList);
transaksiArrayList.add(parentModel);
}
parentAdapter = new TransaksiAdapterParent(transaksiArrayList, getContext());
recyclerView.setAdapter(parentAdapter);
parentAdapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("TAG", "Error : " + error.getMessage());
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show();
}
});
requestQueue.add(stringRequest);
}
这可能不是最好的解决方案,如果我找到更好的解决方案,我相信我会再次更改它,但如果目标只是用数据填充嵌套的 RecyclerView,那么这个解决方案应该足够好。
我想做的是一个蛋糕店的菜单列表,菜单有3个类别,每个类别有不同的菜单.
所以我已经有一个嵌套的 RecyclerView,我的问题是当我想将 RecyclerView 与数据库连接时。我可以在片段中轻松地为父 RecyclerView 创建 Volley,但是很难为子 RecyclerView 创建 StringRequest 方法,因为我必须在 parent RecyclerView 的适配器.[=15= 中设置它]
更新
我缩小了我的问题范围,我已经知道如何在父级适配器中创建方法。现在我的子 RecyclerView StringRequest 有另一个问题。
根据我看到的教程 here,要用不同的菜单填充每个类别,我必须这样做:
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
ParentModel currentItem = parentModelArrayList.get(position);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(cxt, LinearLayoutManager.HORIZONTAL, false);
holder.childRecyclerView.setLayoutManager(layoutManager);
holder.childRecyclerView.setHasFixedSize(true);
holder.category.setText(currentItem.movieCategory());
ArrayList<ChildModel> arrayList = new ArrayList<>();
// added the first child row
if (parentModelArrayList.get(position).movieCategory().equals("Category1")) {
arrayList.add(new ChildModel(R.drawable.themartian,"Movie Name"));
arrayList.add(new ChildModel(R.drawable.moana,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.mov2,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.blackp,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi2,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood1,"Movie Name"));
}
// added in second child row
if (parentModelArrayList.get(position).movieCategory().equals("Category2")) {
arrayList.add(new ChildModel(R.drawable.moviedubbedinhindi2,"Movie Name"));
arrayList.add(new ChildModel(R.drawable.moviedubbedinhindi3,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi1,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi4,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi5,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.moviedubbedinhindi6,"Movie Name"));
}
// added in third child row
if (parentModelArrayList.get(position).movieCategory().equals("Category3")) {
arrayList.add(new ChildModel(R.drawable.hollywood6,"Movie Name"));
arrayList.add(new ChildModel(R.drawable.hollywood5,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood4,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood3,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood2,"Movie Name"));
arrayList.add(new ChildModel( R.drawable.hollywood1,"Movie Name"));
}
ChildRecyclerViewAdapter childRecyclerViewAdapter = new ChildRecyclerViewAdapter(arrayList,holder.childRecyclerView.getContext());
holder.childRecyclerView.setAdapter(childRecyclerViewAdapter);
}
我自己尝试时成功了,但是当我尝试使用 Volley 获取数据时,我总是遇到问题,大多数时候问题是 StringRequest 使用相同的数据。所以我的问题是 如何使用 Volley 做同样的事情?
更新 2
今天我尝试使用我从其他 post 那里学到的 VolleyCallback 接口获取 StringRequest 中的值,首先我想通过只获取 name 值并将其传递给 onBindViewHolder。不幸的是,它失败了,虽然 ViewHolder 中的变量正确接收了值,但 onBindViewHolder 中的变量 returns null
这是界面:
public interface VolleyCallback {
void onSuccess(String result);
}
这是ViewHolder里面的方法class :
public void loadChildMenu(int categoryId, final VolleyCallback callback) {
RequestQueue requestQueue = Volley.newRequestQueue(context);
StringRequest stringRequest = new StringRequest(Request.Method.POST, Servers.VIEW_TRANSC_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("Response", response);
try {
JSONObject obj = new JSONObject(response);
JSONArray jArray = obj.getJSONArray("result");
for (int i = 0; i < jArray.length(); i++) {
JSONObject jObj = jArray.getJSONObject(i);
name = jObj.getString("name");
Log.e("TAG", "Name = " + name);
ModelTransaksi modelTransaksi = new ModelTransaksi();
modelTransaksi.setId(jObj.getInt("idmenu"));
modelTransaksi.setName(jObj.getString("name"));
modelTransaksi.setImage(jObj.getString("image"));
modelTransaksi.setPrice1(jObj.getInt("price1"));
modelTransaksi.setPrice2(jObj.getInt("price2"));
modelTransaksi.setSize(!jObj.getString("size").equals("0"));
dataChild.add(modelTransaksi);
}
callback.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("TAG", "Error : " + error.getMessage());
Toast.makeText(context, error.getMessage(), Toast.LENGTH_LONG).show();
}
}) {
@Nullable
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("idcat", String.valueOf(categoryId));
return params;
}
};
requestQueue.add(stringRequest);
}
这就是我在 onBindViewHolder 中调用它的方式:
//Add first child row
if (dataList.get(position).getIdCategory() == 1) {
holder.loadChildMenu(1, new VolleyCallback() {
@Override
public void onSuccess(String result) {
name = result;
}
});
Log.e("TAG2", "Name2 = " + name);
dataChild.add(new ModelTransaksi(name, 1000, 2000, "kacang.png"));
}
折腾了一周,终于找到办法了
我的解决方案的关键是使用一个 StringRequest 来填充 parent 和 child 适配器。首先,我所做的是使用一个 php 文件获取 parent 和 child 的数据,我就是这样做的:
<?php
include_once("../koneksi.php");
$sql = "SELECT * FROM menu";
$sql2 = "SELECT * FROM menu_category";
$query = mysqli_query($con, $sql);
$query2 = mysqli_query($con, $sql2);
$result = array();
$result2 = array();
while($row = mysqli_fetch_array($query)) {
array_push($result, array(
"idmenu"=>$row['id_menu'],
"category"=>$row['id_category'],
"name"=>$row['menu_name'],
"image"=>$row['menu_image'],
"size"=>$row['menu_size'],
"price1"=>$row['price1'],
"price2"=>$row['price2']
));
}
while($row2 = mysqli_fetch_array($query2)) {
array_push($result2, array(
"category"=>$row2['id_category'],
"catname"=>$row2['cat_name'],
));
}
echo json_encode(array('result'=>$result, 'result2'=>$result2));
mysqli_close($con);
?>
然后在StringRequest中,一次获取所有数据。我就是这样做的:
private void loadCategory() {
RequestQueue requestQueue = Volley.newRequestQueue(getContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, Servers.VIEW_TRANSC_URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
//Get parent's data
JSONObject obj = new JSONObject(response);
JSONArray jArray = obj.getJSONArray("result2");
Log.d("response", String.valueOf(jArray));
for (int i = 0; i < jArray.length(); i++) {
JSONObject jObj = jArray.getJSONObject(i);
ModelTransaksiParent parentModel = new ModelTransaksiParent();
parentModel.setIdCategory(jObj.getInt("category"));
parentModel.setTransaksiCategory(jObj.getString("catname"));
//Get child data
JSONObject childObj = new JSONObject(response);
JSONArray childArray = childObj.getJSONArray("result");
ArrayList<ModelTransaksi> childList = new ArrayList<>();
for (int j=0; j < childArray.length(); j++) {
JSONObject cObj = childArray.getJSONObject(j);
if (jObj.getInt("category") == cObj.getInt("category")) {
childList.add(new ModelTransaksi(cObj.getString("name"), cObj.getInt("price1"), cObj.getInt("price2"), cObj.getString("image")));
}
}
parentModel.setDataChild(childList);
transaksiArrayList.add(parentModel);
}
parentAdapter = new TransaksiAdapterParent(transaksiArrayList, getContext());
recyclerView.setAdapter(parentAdapter);
parentAdapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("TAG", "Error : " + error.getMessage());
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show();
}
});
requestQueue.add(stringRequest);
}
这可能不是最好的解决方案,如果我找到更好的解决方案,我相信我会再次更改它,但如果目标只是用数据填充嵌套的 RecyclerView,那么这个解决方案应该足够好。