【问题标题】:Using RecyclerView.setAdapter from worker thread从工作线程使用 RecyclerView.setAdapter
【发布时间】:2017-02-16 12:46:59
【问题描述】:

使用 memberRecList RecyclerView,我试图水平列出组中的每个成员,但是在设置其适配器时出现此问题:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

注意:我在 cmets 中包含了一些注释,滚动到底部查看它们。

这里是 RecycleView 的初始化:

// I do InitMemberList() in the OnCreate method of my activity
private void InitMemberList()
{
    LinearLayoutManager layoutManager =
        new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);

    memberRecList = (RecyclerView) findViewById(R.id.member_list);
    memberRecList.setHasFixedSize(true);
    memberRecList.setLayoutManager(layoutManager);
    //NOTE 1 (scroll to bottom)
 }

我的数据集是 ArrayList members。我使用 FirebaseDatabase 从工作线程中检索它,如下所示:

 //this is also in the OnCreate() method, doesn't matter if it's before
 //or after InitMembersList() because it starts a separate thread.
 //I'm showing it just in case I have any errors here
 private void GetMemberInfo(final String userId)
 {
    //NOTE 2 (scroll to bottom)
    //Getting the reference of the database
    DatabaseReference ref = userDB.getReference().getRef();
    Query query = ref.child(userId);
    //Firebase's method names are confusing. These below just retrieve the
    //data from the database ONCE.
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            tempMember = dataSnapshot.getValue(User.class); //Getting member info
            members.add(tempMember); //adding member info to the list
            memberCount --; //number of members left to retrieve
            if(memberCount == 0) { 
            //NOTE 3 (scroll to bottom)
            PopulateMemberList(); //the adapter is set inside here
            }

        }
        @Override
        public void onCancelled(DatabaseError databaseError) {}
     });
}

我在 PopulateMemberList() 方法中设置 members 适配器,如下所示:

private void PopulateMemberList()
{
    MembersListAdapter adapter = new MembersListAdapter(members);
    memberRecList.setAdapter(adapter);
}

这是我的自定义 MembersListAdapter

public class MembersListAdapter extends RecyclerView.Adapter<MembersListAdapter.MemberViewHolder> {

    private ArrayList<User> users = new ArrayList<>();

    public MembersListAdapter(ArrayList<User> users) {
        this.users = users;
    }

    public class MemberViewHolder extends RecyclerView.ViewHolder{
        TextView rep_txt;
        ImageView memberImageView;

        public MemberViewHolder(View itemView) {
            super(itemView);
            rep_txt = (TextView) itemView.findViewById((R.id.member_rep_text));
            memberImageView = (ImageView) itemView.findViewById(R.id.member_profile_image);
        }
    }

    @Override
    public int getItemCount() {
        return users.size();
    }

    @Override
    public MemberViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //NOTE 4 (scroll to bottom)
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.member_list_item, parent, true);
        return new MemberViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MemberViewHolder holder, int position) {
            final User currentMember = users.get(position);

            //changing the text of my textviews

            //Loading Member Image
            Picasso.with(GroupActivity.this)
                    .load(currentMember.getProfile_picture_ref())
                    .into(holder.memberImage);
    }

注意事项:

注意 1:我首先尝试在 InitMemberList() 中将 memberRecList 适配器设置为空适配器,然后在从 Firebase 获取数据后设置新适配器。没用。给了我同样的错误。

注意 2: 我在一个循环中使用 GetMemberInfo(),并在其中一一传递 userId。 Firebase 大师会告诉我改为使用 dataSnapshot.getChildren() 创建一个 foreach 循环来逐个检索用户然后过滤它们,但由于我的数据库的大小,这是不可行的。我会扫描一百万用户来检索其中的 5 个。

注意 3: 使用 memberCount 查找成员列表检索是否完成允许我在 之后开始处理数据>完全检索。如果没有这个,尝试访问数据会出现 Nullpointerexception,因为大部分数据都无法及时接收。

注意 4: 我假设这是我的错误所在?我尝试获取 itemView 父级,然后从中删除 **itemView* (正是错误消息说我应该做的):

        @Override
    public MemberViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.member_list_item, parent, true);

        ViewGroup mParent = (ViewGroup) itemView.getParent();
        if(mParent!=null)
            mParent.removeView(itemView);

        return new MemberViewHolder(itemView);
    }

但我收到一百万个以下错误实例:

E/AndroidRuntime: at android.view.ViewGroup.resetResolvedLayoutDirection(ViewGroup.java:6688)

然后是 StackOverflow 错误和应用程序崩溃:

D/Error: ERR: exClass=java.lang.StackOverflowError
D/Error: ERR: exMsg=stack size 8MB
D/Error: ERR: file=ViewGroup.java
D/Error: ERR: class=android.view.ViewGroup
D/Error: ERR: method=resetResolvedLayoutDirection line=6687
D/Error: ERR: stack=java.lang.StackOverflowError: stack size 8MB

在 android.view.ViewGroup.resetResolvedLayoutDirection(ViewGroup.java:6687)

之后,最后一行重复至少 100 次并在最后:

D/Error: ERR: TOTAL BYTES WRITTEN: 41276

编辑: 忘了提,我知道 FirebaseRecyclerAdapter 存在,但我不能使用它。如果您知道其他可以帮助我的图书馆,请告诉我。此外,我更喜欢使用 ListView 而不是 RecyclerView,但我需要水平列出项目(以便我可以向左/向右滚动),我认为使用 ListView 是不可能的。

【问题讨论】:

    标签: java android firebase android-recyclerview android-viewholder


    【解决方案1】:

    您因此获得了IllegalStateException

     @Override
        public MemberViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //NOTE 4 (scroll to bottom)
            View itemView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.member_list_item, parent, true);
            return new MemberViewHolder(itemView);
        }
    

    当您为 RecyclerView 扩展视图时,您不应将其添加到其父级,android 会为您执行此操作。 在以下行中将标志更改为 false 以不向父级添加视图:

     View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.member_list_item, parent, false);
    

    【讨论】:

    • 谢谢!将其设置为 false 修复它!然后这使我认为这个问题重复了,因为我在别人的问题上看到了同样的错误,而答案正是说将最后一个参数更改为假。我不敢相信我也忘记在我的代码中更改它。呃。
    • 很高兴为您提供帮助。不要担心它经常发生,主要是因为即使你没有指定标志,那么默认值是true,你仍然会得到异常。
    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多