I'm working on an Android app which uses PHP API and retrofit. My SQL database has an "orders" table which is the result of join between "users" and "foods" tables. My code works successfully in showing "users" and "foods" in recyclerviews in different fragments, but the same method fails to show the "orders" and I get an empty recyclerview (with the right numbers of rows and items of the orders table) but the strings are null and the integers are 0. The code runs with no error. I also tested PHP request in POSTMAN and the response is correct, so the PHP code is working well. Could you please tell me what is wrong with this code? Could the problem be related to using columns of other tables in the join query or something else? Please help me friends.
I found this in Logcat: 2019-08-08 00:43:52.967 21951-21951/com.nikappzaar.app.foodtakeout E/RecyclerView: No adapter attached; skipping layout
public function getAllOrders(){
$stmt = $this->con->prepare(
"SELECT o.oid, o.uid, o.fid, o.quantity, o.otime
, f.fname, f.unitprice
, u.phone, u.uname, u.uaddress
FROM orders o
INNER JOIN foods f
on o.fid = f.fid
INNER JOIN users u
on o.uid = u.uid ;");
$stmt->execute();
$stmt->bind_result($oid, $uid, $fid, $quantity, $otime, $fname, $unitprice, $phone, $uname, $uaddress);
$orders = array();
while($stmt->fetch()){
$order = array();
$order['o.oid'] = $oid;
$order['o.uid'] = $uid;
$order['o.fid'] = $fid;
$order['o.quantity']=$quantity;
$order['o.otime'] = $otime;
$order['f.fname'] = $fname;
$order['f.unitprice'] = $unitprice;
$order['u.phone']=$phone;
$order['u.uname'] = $uname;
$order['u.uaddress'] = $uaddress;
array_push($orders, $order);
}
return $orders;
}
OperatorHomeFargment.java
public class OperatorHomeFragment extends Fragment {
private RecyclerView recyclerView;
private OrdersAdapter adapter;
private List<Order> orderList;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_orders, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
Call<OrdersResponse> call = RetrofitClient.getInstance().getApi().getOrders();
call.enqueue(new Callback<OrdersResponse>() {
@Override
public void onResponse(Call<OrdersResponse> call, Response<OrdersResponse> response) {
orderList = response.body().getOrders();
adapter = new OrdersAdapter(getActivity(), orderList);
recyclerView.setAdapter(adapter);
}
@Override
public void onFailure(Call<OrdersResponse> call, Throwable t) {
}
});
}
}
OrdersAdapter.java
public class OrdersAdapter extends RecyclerView.Adapter<OrdersAdapter.OrdersViewHolder> {
private Context mCtx;
private List<Order> orderList;
public OrdersAdapter(Context mCtx, List<Order> orderList) {
this.mCtx = mCtx;
this.orderList = orderList;
}
@NonNull
@Override
public OrdersViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mCtx).inflate(R.layout.recyclerview_orders, parent, false);
return new OrdersViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull OrdersViewHolder holder, int position) {
Order order = orderList.get(position);
holder.textViewOId.setText(String.format("%d", order.getOId()));
holder.textViewOTime.setText(order.getOTime());
holder.textViewFName.setText(order.getFName());
holder.textViewQuantity.setText(String.format("%d", order.getQuantity()));
holder.textViewUnitPrice.setText(String.format("%d", order.getUnitPrice()));
holder.textViewPhone.setText(order.getPhone());
holder.textViewUName.setText(order.getUName());
holder.textViewUAddress.setText(order.getUAddress());
}
@Override
public int getItemCount() {
return orderList.size();
}
class OrdersViewHolder extends RecyclerView.ViewHolder {
TextView textViewOId, textViewOTime, textViewFName, textViewQuantity, textViewUnitPrice,
textViewPhone, textViewUName, textViewUAddress;
public OrdersViewHolder(View itemView) {
super(itemView);
textViewOId = itemView.findViewById(R.id.textViewOId);
textViewOTime = itemView.findViewById(R.id.textViewOTime);
textViewFName = itemView.findViewById(R.id.textViewFName);
textViewQuantity = itemView.findViewById(R.id.textViewQuantity);
textViewUnitPrice = itemView.findViewById(R.id.textViewUnitPrice);
textViewPhone = itemView.findViewById(R.id.textViewPhone);
textViewUName = itemView.findViewById(R.id.textViewFName);
textViewUAddress = itemView.findViewById(R.id.textViewUAddress);
}
}
}
Order.java
public class Order {
private int oid, uid, fid, quantity, unitprice;
private String otime, fname, phone, uname, uaddress;
public Order(int oid, int uid, int fid, int quantity, String otime,
String fname, int unitprice, String phone, String uname, String uaddress) {
this.oid = oid;
this.uid = uid;
this.fid = fid;
this.quantity = quantity;
this.otime = otime;
this.fname = fname;
this.unitprice = unitprice;
this.phone = phone;
this.uname = uname;
this.uaddress = uaddress;
}
public int getOId() {
return oid;
}
public int getUId() {
return uid;
}
public int getFId() {
return fid;
}
public int getQuantity() {
return quantity;
}
public String getOTime() {
return otime;
}
public String getFName() {
return fname;
}
public int getUnitPrice() {
return unitprice;
}
public String getPhone() {
return phone;
}
public String getUName() {
return uname;
}
public String getUAddress() {
return uaddress;
}
}
recyclerview_orders.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="3dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dp">
<TextView
android:id="@+id/textViewOId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewOTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewFName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline" />
<TextView
android:id="@+id/textViewQuantity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewUnitPrice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewPhone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
<TextView
android:id="@+id/textViewUName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline" />
<TextView
android:id="@+id/textViewUAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium" />
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
fragment_orders.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
As I understand from comments that you have a problem with parsing response json to model class. Can you try to put a default constructor in Order
class and @SerializedName("json_key_name")
annotation to top of the attributes which has different name from json keys.