首页 文章

添加时,RecyclerView addInArray错误

提问于
浏览
0

当我在 loadOrdersData() 中添加 List<OrderList> 任何项目时,它会抛出:

D / ViewGroup:已调用addInArray,这= android.support.v7.widget.RecyclerView {41cab8f0 VFED .... .F .... ID 0,0-480,770#7f0c0073 app:id / rv} call stack = java.lang.Throwable:android.view.View中的addInArray,以及android.view.View中的android.view.addInArray(ViewGroup.java:3786),以及android.view.View中的addInArray(ViewGroup.java:3740) . (ViewGroup.java: 3564)在android.sview.ViewGroup.addView(ViewGroup.java:3509)的android.support.v7.widget.RecyclerView $ 5.addView(RecyclerView.java:649)android.support.v7.widget.ChildHelper.addView( ChildHelper.java:107)在android.support.v7.widget.RecyclerView $ LayoutManager.addViewInt(RecyclerView.java:7115)在android.support.v7.widget.RecyclerView $ LayoutManager.addView(RecyclerView.java:7073)在android .support.v7.widget.RecyclerView $ LayoutManager.addView(RecyclerView.java:7061),位于android.support.v7.widget.LinearLayoutManager.fill的android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1428) (LinearLayoutManager.jav a:1377)在android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3315)android.support.v7.widget .AvcyclerView.dispatchLayout(RecyclerView.java:3124)位于android.view的android.view.View.layout(View.java:15125)的android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3568) . 在android.view.ViewGroup的android.view.View.layout(View.java:15125)的android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:1197)上的ViewGroup.layout(ViewGroup.java:4862) .layout(ViewGroup.java:4862)在Android.widget.FrameLayout.layout中的android.widget.FrameLayout.layoutChildren(FrameLayout.java:515) . 在android.view.View.layout(查看时)的android.widget.FrameLayout.onLayout(FrameLayout.java:450) . java:15125)在android.view.View.lay(View.java: . :15125)在android.view位于Android.widget.FoutLayout.onLayout(FrameLayout.java:450)android.view.layout((LinkLayout.java:415)android.view.layout(ViewLayout.java:415)在Android.widget.LinearLayout.layoutVertical的android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888)的android.view.ViewGroup.layout(ViewGroup.java:4862)上查看.java:15125(LinearLayout.java:1742 )在Android.widget.Linout.onLayout(LinearLayout.java:1651)的android.view.View.layout(View.java:15125)android.view.Viewout上的android.view.ViewGroup.layout(ViewGroup.java:4862) .FrameLayout.layoutChildren(FrameLayout.java:515)位于android.view.View.Viewout.Lout的Android.view.FoutLayout.onLayout(FrameLayout.java:450)android.view.View.layout(View.java:15125) ViewGroup.java:4862)在android.view.ViewRootImpl.performLversout(ViewRootImpl.java:2323)的android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2029)android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1192) ) 在在Android.view.Choreographer $ CallbackRecord.run(Choreographer.java:788)的android.view.Choreographer.doCallbacks(Choreographer.java:591)android.view.ViewRootImpl $ TraversalRunnable.run(ViewRootImpl.java:6231) .view.Choreographer.doFrame(Choreographer.java:560)在android.view.Chore上的android.view.Handler.handleCallback(Handler.java:808)的android.view.Choreographer $ FrameDisplayEventReceiver.run(Choreographer.java:774) . 在android.app.Looper.loop(Looper.java:193)上的Handler.dispatchMessage(Handler.java:103)位于android.app.ActivityThread.main(ActivityThread.java:5305)的java.lang.reflect.Method.invokeNative (本地方法)位于com.android.internal.os的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:824)的java.lang.reflect.Method.invoke(Method.java:515) .zygoteInit.main(ZygoteInit.java:640)at dalvik.system.NativeStart.main(Native Method)

我尝试在 setAdapter() 之前添加: adapter.notifyDataSetChanged(); ,但没有任何意义 . 有谁看到它是由什么引起的?

这是代码:

主要活动:

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);
        }
    }

}

@布局/ 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>

@布局/ 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 . 如果我将自定义数据输入 listItems ,则无需日志警告即可完美运行 .

6 回答

  • 1

    使用

    adapter = new RecycleAdapter(listItems, CourierActivity.this);
    

    代替

    adapter = new RecycleAdapter(listItems, getApplicationContext());
    

    还要在 RecyclerView 中添加方向

    android:orientation="vertical"
    

    更新此:

    String rsp = new String(response.getBytes(), "UTF-8");
    
  • 1

    试试这种方式

    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>
    
  • 1

    我做了几处修改并写了评论 . 试试看,

    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);
        }
    }
    
  • 1

    Volley似乎是异步获取数据,因此管理 RecyclerView 的最合理方法是首先使用空(但不为空) ListActivity 上下文(例如 Mainactivity.this )设置适配器 .

    当Volley终于得到了全部元素,你添加所有这些(而不是 for(int i = 0; i < orders.length(); i++) 你可以使用 for(OrderListItem listItem : orders); ),你可以调用 adapter.notifyDataSetChanged()

  • 1

    而不是在 onResponse() 中创建新的 ArrayListRecyclerAdapter 实例,我更喜欢,

    • 清除 listItems .

    • 将所有 OrderListItem 实例添加到 listItems .

    • adapternotifyDataSetChanged() .

    例如:

    @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();
         }
    }
    

    并确保正确初始化 RecyclerAdapter ,因为我没有在 CourierActivityonCreate() 方法中看到任何创建 listItems 的代码 .

    listItems = new ArrayList<OrderListItem>();
     adapter = new RecycleAdapter(listItems, getApplicationContext());
    
  • 1

    不要将 list 对象从活动传递给适配器 . 而是在适配器中有一个单独的数组列表 . 将适配器构造函数更改为:

    public RecycleAdapter(List<OrderListItem> listItems, Context context) {
             this.listItems = new ArrayList<>(listItems);
             this.context = context;
        }
    

    并且正如Maddy建议在适配器中使用setMethod传递listitem数组并向其添加所有项并调用notifyDataSetChanged .

    我想这应该解决你的问题,当你不在活动和适配器中使用相同的listitems对象 .

相关问题