【问题标题】:RecyclerView with SearchView. List will only start to show when typing a text on searchView带有 SearchView 的 RecyclerView。只有在 searchView 上输入文本时,列表才会开始显示
【发布时间】:2016-03-15 10:38:52
【问题描述】:

我正在通过Github Repository 的 searchView 应用程序使用这个 recyclerView

我所做的唯一更改不是从字符串数组中获取结果,而是使用 volley 从 Web 服务器检索数据。我还添加了一个单例类,因为 volley 需要它。我得到的唯一问题是,在应用程序启动时,列表不会显示,直到我单击搜索图标并在其上键入一些文本/字符。我很确定我能够从网络服务器检索数据,因为它会在搜索视图中键入内容时显示出来。尝试测试一下,如果你能解决它,请告诉我。

在 repo 上,MainFragment 看起来与下面的代码相同,只是添加了用于从服务器获取数据的代码。看看我的代码:

    public class MainFragment extends Fragment implements SearchView.OnQueryTextListener {

    public static MainFragment newInstance() {
        return new MainFragment();
    }
    private static String url = "http://www.psite7.org/portal/webservices/get_members.php";

    private static final String[] MOVIES = new String[]{
            "The Woman in Black: Angel of Death",
            "20 Once Again",
            "Taken 3",
            "Tevar",
            "I",
            "Blackhat",
            "Spare Parts",
            "The Wedding Ringer",
            "Ex Machina",
            "Mortdecai",
            "Strange Magic",
            "The Boy Next Door",
            "The SpongeBob Movie: Sponge Out of Water",
            "Kingsman: The Secret Service",
            "Boonie Bears: Mystical Winter",
            "Project Almanac",
            "Running Man",
            "Wild Card",
            "It Follows",
            "C'est si bon",
            "Yennai Arindhaal",
            "Shaun the Sheep Movie",
            "Jupiter Ascending",
            "Old Fashioned",
            "Somewhere Only We Know",
            "Fifty Shades of Grey",
            "Dragon Blade",
            "Zhong Kui: Snow Girl and the Dark Crystal",
            "Badlapur",
            "Hot Tub Time Machine 2",
            "McFarland, USA",
            "The Duff",
            "The Second Best Exotic Marigold Hotel",
            "A la mala",
            "Focus",
            "The Lazarus Effect",
            "Chappie",
            "Faults",
            "Road Hard",
            "Unfinished Business",
            "Cinderella",
            "NH10",
            "Run All Night",
            "X+Y",
            "Furious 7",
            "Danny Collins",
            "Do You Believe?",
            "Jalaibee",
            "The Divergent Series: Insurgent",
            "The Gunman",
            "Get Hard",
            "Home"
    };

    private RecyclerView mRecyclerView;
    private ExampleAdapter mAdapter;
    private List<ExampleModel> mModels;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_main, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);

        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        setHasOptionsMenu(true);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        mModels = new ArrayList<>();

//        for (String movie : MOVIES) {
//            mModels.add(new ExampleModel(movie));
//        }
        populate();
//        mAdapter = new ExampleAdapter(getActivity(), mModels);
//        mRecyclerView.setAdapter(mAdapter);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_main, menu);

        final MenuItem item = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
        searchView.setOnQueryTextListener(this);
    }

    @Override
    public boolean onQueryTextChange(String query) {
        final List<ExampleModel> filteredModelList = filter(mModels, query);
        mAdapter.animateTo(filteredModelList);
        mRecyclerView.scrollToPosition(0);
        return true;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        return false;
    }

    private List<ExampleModel> filter(List<ExampleModel> models, String query) {
        query = query.toLowerCase();

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

    public void populate(){
        JsonArrayRequest request = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray jsonArray) {
//                        hidePDialog();
                        String   email, status;
//                        Member member;
                        final String names[] = new String[jsonArray.length()];
                        for(int i = 0; i < jsonArray.length(); i++) {
                            try {
                                JSONObject object = jsonArray.getJSONObject(i);

                                names[i] = object.getString("firstname") + " " + object.getString("lastname");
                                email = object.getString("email");
                                if(Integer.parseInt(object.getString("activated"))==1){
                                    status = "Active";
                                }else{
                                    status = "Not Active";
                                }
//                                member = new Member(name, email, status);

                            } catch (Exception e) {

                            }
                        }
                        for(String name : names){
                            Log.wtf("name", name);
                            mModels.add(new ExampleModel(name));
                        }
                        mAdapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener(){
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                volleyError.printStackTrace();
            }
        });
        AppController.getInstance().addToRequestQueue(request);
        mAdapter = new ExampleAdapter(getActivity(), mModels);
        mRecyclerView.setAdapter(mAdapter);
    }
}

如果您注意到我刚刚评论了回购中使用的代码。我试图尽可能地复制它。

【问题讨论】:

  • 我所做的唯一改变......
  • First, try learn how to ask before asking ... 您的问题是题外话:寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处
  • 您是在视频群聊中偶然与我联系的同一个人吗? :-)
  • @XaverKapeller 是的,是我,哈哈
  • 问题很简单:您混淆了同步和异步代码。 Response.Listener 中发生的事情发生在 populate() 完成执行很久之后。所以正如我昨天在我们第一次谈论这个时告诉你的那样:问题是你在创建它时没有将完整的模型列表传递给Adapeter。您传递一个空列表,然后一段时间后您将对象添加到mModels,然后当您第一次过滤或执行任何触发过滤操作的操作时,这些对象将添加到Adapter 的内部列表中并且开始出现。

标签: android android-recyclerview android-volley searchview


【解决方案1】:

您正在混淆同步和异步代码。如果在将所有模型添加到 mModels 后创建并分配 ExampleAdapter,它应该可以按预期工作。

1) 修复代码

public void populate() {
    final JsonArrayRequest request = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {

        @Override
        public void onResponse(JSONArray jsonArray) {
            try {
                for (int i = 0; i < jsonArray.length(); i++) {
                    final JSONObject object = jsonArray.getJSONObject(i);
                    final String name = object.getString("firstname") + " " + object.getString("lastname");
                    mModels.add(new ExampleModel(name));
                }
                mAdapter = new ExampleAdapter(getActivity(), mModels);
                mRecyclerView.setAdapter(mAdapter);
            } catch (JSONException e) {
                Log.e(LOG_TAG, "Failed to parse member json.", e);
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            volleyError.printStackTrace();
        }
    });
    AppController.getInstance().addToRequestQueue(request);
}

2) 更好的解决方案

更好的是在onViewCreated() 中创建一次Adapter,然后在模型列表发生变化时使用animateTo() 方法:

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    mAdapter = new ExampleAdapter(getActivity(), new ArrayList<>());
    mRecyclerView.setAdapter(mAdapter);
    ...
    updateMemberList();
}

public void updateModels() {
    final JsonArrayRequest request = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {

        @Override
        public void onResponse(JSONArray jsonArray) {
            try {
                for (int i = 0; i < jsonArray.length(); i++) {
                    final JSONObject object = jsonArray.getJSONObject(i);
                    final String name = object.getString("firstname") + " " + object.getString("lastname");
                    mModels.add(new ExampleModel(name));
                }
                mAdapter.animateTo(mModels);
            } catch (JSONException e) {
                Log.e(LOG_TAG, "Failed to parse member json.", e);
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            volleyError.printStackTrace();
        }
    });
    AppController.getInstance().addToRequestQueue(request);
}        

这两件事都有效,正如您尝试的那样 - 修改了您的 Fragment 中的 List - 无效。 Adapter 有自己的内部模型 List,如果您想更改 RecyclerView 中显示的内容,您需要修改它。

【讨论】:

  • 这真是太棒了!只需传输两行代码即可解决!哇,搞了两天了。非常感谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 2016-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
相关资源
最近更新 更多