Friday, December 8, 2017

RecyclerView addInArray error when adding

Leave a Comment

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,

  1. Clear listItems.
  2. Add all OrderListItem instance to listItems.
  3. Call 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());         

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.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment