【问题标题】:RecyclerView not populated until SearchView interaction在 SearchView 交互之前不会填充 RecyclerView
【发布时间】:2016-03-26 14:24:51
【问题描述】:

我的 recyclerview 有一个问题,它有一个自定义适配器。问题是当活动打开时,recyclerview 是空的。当用户在 SearchView 的文本字段中键入任何内容时,recyclerview 会被填充并保持填充状态而不会出现任何问题。我试图改变一些代码的位置来解决这个问题,但没有成功。我在代码下方添加了当前和所需状态的屏幕截图。提前致谢。

添加课程活动:

public class AddCourseActivity extends AppCompatActivity{

private RecyclerView mRecyclerView;
private AddCourseAdapter mAdapter;
private List<AddCourseAdapter.AddCourseModel> mModels;
SearchView mSearchView;

@Override
protected void onCreate(Bundle savedInstance) {
    super.onCreate(savedInstance);
    setContentView(R.layout.activity_add_course);
    Kii.initialize(AppConstants.APP_ID, AppConstants.APP_KEY,
            AppConstants.APP_SITE);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setDisplayShowHomeEnabled(true);
    mRecyclerView = (RecyclerView) findViewById(R.id.addcourseRecyclerView);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    String[] courses = new String[]{
            "Math119",
            "Enve101",
            "Chem107",
            "Chem229",
            "Phys105",
            "Math120"};
    mModels = new ArrayList<>();
    mAdapter = new AddCourseAdapter(this, mModels);
    mSearchView = (SearchView) findViewById(R.id.searchView);
    mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }
        @Override
        public boolean onQueryTextChange(String newText) {
            final List<AddCourseAdapter.AddCourseModel> filteredModelList = filter(mModels, newText);
            mAdapter.animateTo(filteredModelList);
            mRecyclerView.scrollToPosition(0);
            return true;
        }
    });
    for (String course: courses) {
        mModels.add(new AddCourseAdapter.AddCourseModel(course));
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
    }
}

private List<AddCourseAdapter.AddCourseModel> filter(List<AddCourseAdapter.AddCourseModel> models, String query) {
    query = query.toLowerCase();
    final List<AddCourseAdapter.AddCourseModel> filteredModelList = new ArrayList<>();
    for (AddCourseAdapter.AddCourseModel model: models) {
        final String text = model.getText().toLowerCase();
        if (text.contains(query)) {
            filteredModelList.add(model);
        }
    }
    return filteredModelList;
}
}

添加课程适配器:

public class AddCourseAdapter extends RecyclerView.Adapter<AddCourseAdapter.AddCourseViewHolder> {
private final LayoutInflater mInflater;
private final List<AddCourseModel> mModels;
KiiUser user;
KiiObject object;
KiiBucket userBucket;
Context context;

public AddCourseAdapter(Context context, List<AddCourseModel> models) {
    mInflater = LayoutInflater.from(context);
    mModels = new ArrayList<>(models);
}

@Override
public AddCourseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    context = parent.getContext();
    final View itemView = mInflater.inflate(R.layout.list_item_add_course, parent, false);
    user = KiiUser.getCurrentUser();
    final String username = user.getUsername();
    userBucket = Kii.user().bucket(username);
    String id = "mycourses";
    object = userBucket.object(id);
    return new AddCourseViewHolder(itemView);
}

@Override
public void onBindViewHolder(final AddCourseViewHolder holder, int position) {
    final AddCourseModel model = mModels.get(position);
    holder.bind(model);
    holder.addButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final String value = holder.mTextView.getText().toString();
            object.refresh(new KiiObjectCallBack() {
                @Override
                public void onRefreshCompleted(int token, @NonNull KiiObject object, Exception exception) {
                    object.set(value, true);
                    object.saveAllFields(new KiiObjectCallBack() {
                        @Override
                        public void onSaveCompleted(int token, KiiObject object, Exception exception) {
                            Toast.makeText(context,
                                    "Added: " + value,
                                    Toast.LENGTH_SHORT)
                                    .show();
                        }
                    }, false);
                }
            });
            holder.addButton.setVisibility(View.GONE);
            holder.removeButton.setVisibility(View.VISIBLE);
        }
    });
    holder.removeButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View v) {
            final String value = holder.mTextView.getText().toString();
            object.refresh(new KiiObjectCallBack() {
                @Override
                public void onRefreshCompleted(int token, @NonNull KiiObject object, Exception exception) {
                    object.set(value, false);
                    object.saveAllFields(new KiiObjectCallBack() {
                        @Override
                        public void onSaveCompleted(int token, @NonNull KiiObject object, Exception exception) {
                            Toast.makeText(context,
                                    "Removed: " + value,
                                    Toast.LENGTH_SHORT)
                                    .show();
                        }
                    }, false);
                }
            });

            holder.addButton.setVisibility(View.VISIBLE);
            holder.removeButton.setVisibility(View.GONE);
        }
    });
}

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

public void animateTo(List<AddCourseModel> models) {
    applyAndAnimateRemovals(models);
    applyAndAnimateAdditions(models);
    applyAndAnimateMovedItems(models);
}

private void applyAndAnimateRemovals(List<AddCourseModel> newModels) {
    for (int i = mModels.size() - 1; i >= 0; i--) {
        final AddCourseModel model = mModels.get(i);
        if (!newModels.contains(model)) {
            removeItem(i);
        }
    }
}

private void applyAndAnimateAdditions(List<AddCourseModel> newModels) {
    for (int i = 0, count = newModels.size(); i < count; i++) {
        final AddCourseModel model = newModels.get(i);
        if (!mModels.contains(model)) {
            addItem(i, model);
        }
    }
}

private void applyAndAnimateMovedItems(List<AddCourseModel> newModels) {
    for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
        final AddCourseModel model = newModels.get(toPosition);
        final int fromPosition = mModels.indexOf(model);
        if (fromPosition >= 0 && fromPosition != toPosition) {
            moveItem(fromPosition, toPosition);
        }
    }
}

public AddCourseModel removeItem(int position) {
    final AddCourseModel model = mModels.remove(position);
    notifyItemRemoved(position);
    return model;
}

public void addItem(int position, AddCourseModel model) {
    mModels.add(position, model);
    notifyItemInserted(position);
}

public void moveItem(int fromPosition, int toPosition) {
    final AddCourseModel model = mModels.remove(fromPosition);
    mModels.add(toPosition, model);
    notifyItemMoved(fromPosition, toPosition);
}

public class AddCourseViewHolder extends RecyclerView.ViewHolder {
    private final TextView mTextView;
    private final ImageButton addButton;
    private final ImageButton removeButton;

    public AddCourseViewHolder(View itemView) {
        super(itemView);
        mTextView = (TextView) itemView.findViewById(R.id.addCourseTV);
        addButton = (ImageButton) itemView.findViewById(R.id.addButton);
        removeButton = (ImageButton) itemView.findViewById(R.id.removeButton);
    }

    public void bind(AddCourseModel model) {
        mTextView.setText(model.getText());
    }
}

public static class AddCourseModel {
   private final String mText;

   public AddCourseModel(String text) {
       this.mText = text;
   }

   public String getText() {
       return mText;
   }
}
}

当前初始状态:

所需的初始状态:

【问题讨论】:

    标签: android android-recyclerview adapter searchview


    【解决方案1】:

    案例在您的适配器构造函数中

    public AddCourseAdapter(Context context, List<AddCourseModel> models) {
        mInflater = LayoutInflater.from(context);
        mModels = new ArrayList<>(models);
    }
    

    您创建了一个新的 ArrayList,它最初是从模型列表中填充的(此时它是空的)。 稍后您填充初始模型数组列表,而不是在适配器中创建的模型。

    你可以:

    a) 移动

    for (String course: courses) {
            mModels.add(new AddCourseAdapter.AddCourseModel(course));
            mRecyclerView.setAdapter(mAdapter);
            mAdapter.notifyDataSetChanged();
        }
    

    在这两行之间

    mModels = new ArrayList<>();
    mAdapter = new AddCourseAdapter(this, mModels);
    

    让自己看起来像这样

    mModels = new ArrayList<>();
    
    for (String course: courses) {
      mModels.add(new AddCourseAdapter.AddCourseModel(course));
    }
    mAdapter = new AddCourseAdapter(this, mModels);
    mRecyclerView.setAdapter(mAdapter);
    

    b) 将 Adapter 构造函数重写为

    public AddCourseAdapter(Context context, List<AddCourseModel> models) {
            mInflater = LayoutInflater.from(context);
            mModels = models;
        }
    

    【讨论】:

    • 哦,我刚出门你就回答了。今天晚些时候我会告诉你的,谢谢
    • 两种解决方案都能胜任。欣赏它。作为旁注,您认为哪一个是更好的解决方案,稳定性和性能方面?我觉得解决方案 b 更好,因为 a 原因做更多的工作。这还重要吗?
    • 没关系。如果您保留对 mModels 列表的引用并计划在适配器之外对其进行更改,则在解决方案 B 中只需要小心。如果你这样做,你总是需要通知适配器有关更改(因为它是列表的同一个实例)。
    • 嘿伙计,我刚刚意识到过滤器逻辑存在问题,在这些安排之前它工作正常。目前,当用户输入诸如“qwerty”之类没有过滤建议的内容时,预计列表为空。但之前,当用户删除输入时,列表再次填充。现在,除非用户重新启动活动,否则它仍然是空的。你知道发生了什么事吗?
    • 您正在对 animateTo 方法中的数组列表进行更改。通常,您保留未过滤列表的副本以供参考
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多