Reputation: 2452
When I add in List<OrderList>
any item in loadOrdersData()
, it throws this:
D/ViewGroup: addInArray been called, this = android.support.v7.widget.RecyclerView {41cab8f0 VFED.... .F....ID 0,0-480,770 #7f0c0073 app:id/rv}call stack = java.lang.Throwable: addInArray at android.view.ViewGroup.addInArray(ViewGroup.java:3786) at android.view.ViewGroup.addViewInner(ViewGroup.java:3740) at android.view.ViewGroup.addView(ViewGroup.java:3564) at android.view.ViewGroup.addView(ViewGroup.java:3509) at android.support.v7.widget.RecyclerView$5.addView(RecyclerView.java:649) at android.support.v7.widget.ChildHelper.addView(ChildHelper.java:107) at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:7115) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:7073) at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:7061) at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1428) at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377) at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578) at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3315) at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3124) at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3568) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1197) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515) at android.widget.FrameLayout.onLayout(FrameLayout.java:450) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:433) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515) at android.widget.FrameLayout.onLayout(FrameLayout.java:450) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1742) at android.widget.LinearLayout.onLayout(LinearLayout.java:1651) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:515) at android.widget.FrameLayout.onLayout(FrameLayout.java:450) at android.view.View.layout(View.java:15125) at android.view.ViewGroup.layout(ViewGroup.java:4862) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2323) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2029) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1192) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6231) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:788) at android.view.Choreographer.doCallbacks(Choreographer.java:591) at android.view.Choreographer.doFrame(Choreographer.java:560) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774) at android.os.Handler.handleCallback(Handler.java:808) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:5305) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640) at dalvik.system.NativeStart.main(Native Method)
I tried adding: adapter.notifyDataSetChanged();
before setAdapter()
in loadOrdersData()
but it makes no sense. Does anyone see what it is caused by?
Here's the code:
MainActivity:
public class CourierActivity extends AppCompatActivity {
private TableLayout orderTable;
private RecyclerView recyclerView;
private RecycleAdapter adapter;
private List<OrderListItem> listItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.courier_main);
recyclerView = (RecyclerView) findViewById(R.id.rv);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(CourierActivity.this));
adapter = new RecycleAdapter(listItems, getApplicationContext());
recyclerView.setAdapter(adapter);
loadOrdersData();
}
private void loadOrdersData() {
RequestQueue queue = Volley.newRequestQueue(this);
StringRequest sr = new StringRequest(Request.Method.GET, URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
listItems = new ArrayList<>();
try {
String rsp = new String(response.getBytes("ISO-8859-1"), "UTF-8");
JSONArray orders = new JSONArray(rsp);
for (int i = 0; i < orders.length(); i++) {
OrderListItem listItem = new OrderListItem(
// ..
);
listItems.add(listItem);
}
adapter = new RecycleAdapter(listItems, getApplicationContext());
recyclerView.setAdapter(adapter);
} catch (JSONException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT);
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
return params;
}
};
queue.add(sr);
}
}
OrderListItem:
public class OrderListItem {
private String name;
private String status;
private String price;
private String courier;
public OrderListItem(String name, String status, String price, String courier) {
this.name = name;
this.status = status;
this.price = price;
this.courier = courier;
}
public String getName() { return name; }
public String getStatus() { return status;}
public String getPrice() { return price; }
public String getCourier() { return courier; }
}
RecycleAdapter:
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> {
private List<OrderListItem> listItems;
private Context context;
public RecycleAdapter(List<OrderListItem> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.rv_item, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
OrderListItem listItem = listItems.get(position);
holder.TextViewName.setText(listItem.getName());
holder.TextViewStatus.setText(listItem.getStatus());
holder.TextViewPrice.setText(listItem.getPrice());
holder.TextViewCourier.setText(listItem.getCourier());
}
@Override
public int getItemCount() {
int count = 0;
if (listItems != null && !listItems.isEmpty()) {
count = listItems.size();
}
return count;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView TextViewName;
public TextView TextViewStatus;
public TextView TextViewPrice;
public TextView TextViewCourier;
public ViewHolder(View itemView) {
super(itemView);
TextViewName = (TextView) itemView.findViewById(R.id.orderListName);
TextViewStatus = (TextView) itemView.findViewById(R.id.orderListStatus);
TextViewPrice = (TextView) itemView.findViewById(R.id.orderListPrice);
TextViewCourier = (TextView) itemView.findViewById(R.id.orderListCourier);
}
}
}
@layout/rv_item.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="wrap_content">
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_margin="@dimen/activity_horizontal_margin"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<LinearLayout
android:padding="@dimen/activity_horizontal_margin"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/orderListName"
android:text="Order name"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/orderListStatus"
android:text="Status"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/orderListPrice"
android:text="Price"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/orderListCourier"
android:text="Courier"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
@layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.seether.myapplication.CourierActivity"
android:background="#fff"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawerLayout">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rv"/>
</android.support.v4.widget.DrawerLayout>
EDIT. Works perfect without log's warnings if I enter custom data into listItems
.
Upvotes: 1
Views: 1286
Reputation: 310
Don't pass the list object from activity to adapter. Instead have a separate array list in adapter. Change your adapter constructor to this:
public RecycleAdapter(List<OrderListItem> listItems, Context context) {
this.listItems = new ArrayList<>(listItems);
this.context = context;
}
And as Maddy suggested use a setMethod in adapter passing the listitem array and adding all items to it and calling notifyDataSetChanged.
I guess this should solve your problem when you don't use the same listitems object in activity and adapter.
Upvotes: 1
Reputation: 5262
Instead of create new ArrayList
and RecyclerAdapter
instance in onResponse()
, I prefer,
listItems
. OrderListItem
instance to listItems
.notifyDataSetChanged()
of adapter
.For example:
@Override
public void onResponse(String response) {
listItems.clear();
try {
//loop and add all items to listItems here
adapter.notifyDataSetChanged();
} catch (JSONException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
and make sure that you initialize RecyclerAdapter
properly because I do not see any code that create listItems
in onCreate()
method of CourierActivity
.
listItems = new ArrayList<OrderListItem>();
adapter = new RecycleAdapter(listItems, getApplicationContext());
Upvotes: 1
Reputation: 545
Volley seems to get the data asynchronously, so the most reasonable way to manage the RecyclerView
is setting the adapter at first with an empty (but not null) List
and the Activity context (e.g. Mainactivity.this
).
When Volley has finally got all the elements, you add all of them (instead of for(int i = 0; i < orders.length(); i++)
you could use for(OrderListItem listItem : orders);
), you can call adapter.notifyDataSetChanged()
Upvotes: 1
Reputation: 2067
I have made couple of changes and written in comment. Try that out,
public class CourierActivity extends AppCompatActivity {
private TableLayout orderTable;
private RecyclerView recyclerView;
private RecycleAdapter adapter;
//********* Initialize over here **********//
private List<OrderListItem> listItems = new ArrayList<>();
private Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.courier_main);
//********** Initialize *******//
mContext = CourierActivity.this;
recyclerView = (RecyclerView) findViewById(R.id.rv);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(CourierActivity.this));
//********* added class context *********//
adapter = new RecycleAdapter(listItems, mContext);
recyclerView.setAdapter(adapter);
loadOrdersData();
}
private void loadOrdersData() {
RequestQueue queue = Volley.newRequestQueue(this);
StringRequest sr = new StringRequest(Request.Method.GET, URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//******** Remove this line *************//
listItems = new ArrayList<>();
//******** Add this line ************//
listItems.clear();
try {
String rsp = new String(response.getBytes("ISO-8859-1"), "UTF-8");
JSONArray orders = new JSONArray(rsp);
for (int i = 0; i < orders.length(); i++) {
OrderListItem listItem = new OrderListItem(
// ..
);
listItems.add(listItem);
}
//*********Remove these both lines **********//
adapter = new RecycleAdapter(listItems, getApplicationContext());
recyclerView.setAdapter(adapter);
//************ Add this line **********//
adapter.notifyDataSetChanged();
} catch (JSONException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT);
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
return params;
}
};
queue.add(sr);
}
}
Upvotes: 1
Reputation: 5043
Try this way
CourierActivity.java
public class CourierActivity extends AppCompatActivity {
...
//Don't forget to intialize your List
private List<OrderListItem> listItems = new ArrayList<OrderListItem>();
...
private void loadOrdersData() {
RequestQueue queue = Volley.newRequestQueue(this);
StringRequest sr = new StringRequest(Request.Method.GET, URL, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
listItems = new ArrayList<>();
try {
String rsp = new String(response.getBytes("ISO-8859-1"), "UTF-8");
JSONArray orders = new JSONArray(rsp);
for (int i = 0; i < orders.length(); i++) {
OrderListItem listItem = new OrderListItem(
// ..
);
listItems.add(listItem);
}
//set list to adapter this way
adapter.setList(listItems);
} catch (JSONException | UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT);
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
return params;
}
};
queue.add(sr);
}
}
RecycleAdapter.java
public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.ViewHolder> {
private List<OrderListItem> listItems;
private Context context;
public RecycleAdapter(List<OrderListItem> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
public setList(List<OrderListItem> listItems){
//add list to parent list and notify your adapter
this.listItems.addAll(listItems);
notifyDataSetChanged();
}
...
}
Edit 1 :
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.example.seether.myapplication.CourierActivity"
android:background="#fff"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawerLayout">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rv"/
</LinearLayout>
Upvotes: 1
Reputation: 103361
Use
adapter = new RecycleAdapter(listItems, CourierActivity.this);
instead of
adapter = new RecycleAdapter(listItems, getApplicationContext());
Also add orientation in your RecyclerView
android:orientation="vertical"
Update this:
String rsp = new String(response.getBytes(), "UTF-8");
Upvotes: 1