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
.
6 Answers
Answers 1
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>
Answers 2
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");
Answers 3
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); } }
Answers 4
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()
Answers 5
Instead of create new ArrayList
and RecyclerAdapter
instance in onResponse()
, I prefer,
- Clear
listItems
. - Add all
OrderListItem
instance tolistItems
. - Call
notifyDataSetChanged()
ofadapter
.
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());
Answers 6
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.
0 comments:
Post a Comment