为嵌套 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,那么这个解决方案应该足够好。