【问题标题】:RecyclerView addInArray error when addingRecyclerView addInArray 添加时出错
【发布时间】:2018-05-12 02:01:25
【问题描述】:

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

D/ViewGroup: addInArray 被调用,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) 在 android.support.v7.widget.RecyclerView$5.addView(RecyclerView.java:649) 在 android.support.v7.widget.ChildHelper 的 android.view.ViewGroup.addView(ViewGroup.java:3509)。 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.layoutChunk(LinearLayoutManager.java:1428) 在 android.support.v7.widget.LinearLayoutManager .fill(LinearLayoutManager.ja va:1377) 在 android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578) 在 android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3315) 在 android.support.v7.widget .RecyclerView.dispatchLayout(RecyclerView.java:3124) 在 android.view.view.view.layout(View.java:15125) 在 android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3568) 在 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) 在 android.widget.FrameLayout.layoutChildren(FrameLayout.java:515) 在 android.widget.FrameLayout.onLayout(FrameLayout.java:450) 在 android.view.View.layout(View. java:15125) 在 android.view.ViewGroup.layout(ViewGroup.java:4862) 在 android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:433) 在 android.view.View.layout(View.java :15125) 在 android.vi ew.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) 在 android.view.ViewGroup.layout(ViewGroup.java:4862) 在 android.widget.LinearLayout.setChildFrame(LinearLayout.java:1888) 在 android.widget.LinearLayout.layoutVertical(LinearLayout.java: 1742) 在 android.view.View.layout(View.java:15125) 在 android.view.ViewGroup.layout(ViewGroup.java:4862) 在 android.widget.LinearLayout.onLayout(LinearLayout.java:1651)。 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) 在 android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2323) 在 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2029) 在 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java: 1192)在 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6231) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:788) 在 android.view.Choreographer.doCallbacks(Choreographer.java:591) 在android.view.Choreographer.doFrame(Choreographer.java:560) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:774) 在 android.os.Handler.handleCallback(Handler.java:808) 在 android.os .Handler.dispatchMessage(Handler.java:103) 在 android.os.Looper.loop(Looper.java:193) 在 android.app.ActivityThread.main(ActivityThread.java:5305) 在 java.lang.reflect.Method。在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824) 在 com.android.internal 的 java.lang.reflect.Method.invoke(Method.java:515) 的 invokeNative(Native Method)。 os.ZygoteInit.main(ZygoteInit.java:640) at dalvik.system.NativeStart.main(Native Method)

我尝试在loadOrdersData() 中的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);
    }
}

订单列表项:

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

回收适配器:

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>

编辑。如果我将自定义数据输入listItems,则可以完美运行而不会出现日志警告。

【问题讨论】:

  • 我首先要知道的是,当您通过“onCreate()”方法传入适配器时,您传递的是 NULL 的“listItems”。在发送之前尝试对其进行初始化。那么让我知道现在发生了什么
  • @ankitpatidar 试过了,也没有意义 :(
  • 把你的“OrderListItem”类放在问题中
  • 您好,请给我们网址,我们可以通过它检查吗?谢谢
  • @ankitpatidar 抱歉,这是一个私人网址。你可以用一个循环来检查它。

标签: java android android-recyclerview


【解决方案1】:

使用

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

而不是

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

还在您的RecyclerView 中添加方向

android:orientation="vertical"

更新这个:

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

【讨论】:

  • 两边都换了吗?
  • 是的,在 onCreate()loadOrdersData() 方法中
  • 是“loadOrdersData()”之后的错误吗?如果您评论该方法会发生什么?
  • 如果我评论该方法,则不会发生任何事情。所以是的,这个错误出现在loadOrdersData()之后
  • 在您的回收站视图中添加 android:orientation="vertical"
【解决方案2】:

试试这个方法

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

编辑 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>

【讨论】:

  • @phen0men,我已经更新了我的答案,请让你的main.xml 像这样
  • 还是不行。我在 main.xml 中有主要的 DrawerLayout 用于 NavigationDrawer。但我试图将其删除并替换为您的代码。问题仍然存在。
  • 我觉得不是因为这个,我做过很多次类似的事情
【解决方案3】:

我做了一些更改并写在评论中。试试看,

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

【讨论】:

  • 您的修改不要在recycleView中添加listItems
  • 我已经在创建适配器对象时添加了 listItems。当您收到响应时,您填写列表项。你需要调用适配器的 notifyDataSetChanged() ,它会自动刷新recycleview @phen0men
  • 您整合了我的更改了吗?
  • 是的,我有。它仍在扔日志。应用程序运行完美,但我担心这些日志。
【解决方案4】:

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

当 Volley 最终得到所有元素时,将它们全部添加(而不是 for(int i = 0; i &lt; orders.length(); i++),您可以使用 for(OrderListItem listItem : orders);),您可以调用 adapter.notifyDataSetChanged()

【讨论】:

  • 我在哪里调用最后一个方法?
  • 只需在 onCreate() 中的setAdapter 之后调用它,但不要再次调用它,也不要在方法内创建它的新实例。
  • 还是一样。我认为是自定义回收适配器引起的问题
  • 你有没有试过不addAll()而是设置值(=)??
  • 是的,我试过了。这种方式不能解决我的问题
【解决方案5】:

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

  1. 清除listItems
  2. 将所有OrderListItem 实例添加到listItems
  3. 致电notifyDataSetChanged()adapter

例如:

@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,因为我没有看到在onCreate()CourierActivity 方法中创建listItems 的任何代码。

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

【讨论】:

    【解决方案6】:

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

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

    正如 Maddy 建议的那样,在适配器中使用 setMethod 传递 listitem 数组并将所有项目添加到其中并调用 notifyDataSetChanged。

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

    【讨论】:

    • 好吧..问题仍然存在。该应用程序运行良好,recycleView 通过RecycleAdapter 中的 this 方法进行了更新。但是在运行日志中,当我在RecycleAdapter 中添加/更新listItems 时,应用程序会抛出太多日志(listItems 中的 3 项 = 3 个日志):pastebin.com/1TGxC4HJ 也许是不是错误,只是日志?
    猜你喜欢
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 2011-05-01
    • 2018-08-07
    • 1970-01-01
    相关资源
    最近更新 更多