【问题标题】:Android Listview Filtering versus RepopulationAndroid Listview 过滤与重新填充
【发布时间】:2012-07-19 16:42:43
【问题描述】:

确实经过一些建议。我的应用程序使用媒体存储光标在加载时填充列表视图。这是提取链接到用户定义文件夹的音乐,在大多数情况下,这将是他们存储的所有音乐。我有一个 beta 测试仪,它使用的是爱可视平板电脑,上面有大约 10000 首歌曲,运行 android 2.2。虽然大多数用户的性能都相当出色,但我想改善这样的用户的体验。

当前进程:

用户加载应用。 应用程序找到默认文件夹 应用程序使用该文件夹内和该文件夹下的音乐填充列表视图 用户移动到树更下方的文件夹,列表视图根据所选文件夹重新填充 用户再次移动....根据所选文件夹重新填充列表...

所以我想知道的是 - 使用以下过程是否更快/更有效: 用户加载应用 应用程序找到默认文件夹 应用程序使用该文件夹内和该文件夹下的音乐填充列表视图 用户移动到树中的文件夹,列表被过滤到该文件夹 如果用户在树上移动到比默认数据更高的位置(即潜在的新文件),则重新填充列表视图,但仅在这种情况下。

所以基本上,我的问题是“过滤与重新填充相比如何?”

【问题讨论】:

    标签: android listview filter android-listview


    【解决方案1】:

    一个很好的问题。让我试着回答一下。

    过滤实际上是重新填充ListView,而您创建/获取一个新集合并通过调用notifyDataSetChanged 告诉Adapter 它的内容已更改。

    listView 的“繁重”工作是 getView 调用它的适配器。我自己对此进行了测试,如果每次调用 getView 时都膨胀一个新视图,性能就会下降。天堂般的。

    ListView 的适配器被构建以便可以重新使用已经膨胀的视图,这解决了上面提到的问题。此外,仅加载可见视图,因此如果您告诉 Adapter 它的集合是 10000 个项目,它不会创建 10000 个视图。

    notifyDataSetChanged 将告诉适配器重建列表视图内容,但它仍然包含以前膨胀的视图。所以这是一个巨大的性能胜利。

    所以我对您的建议是,当您使用相同的“行布局”时,只需使用notifyDataSetChanged 重新填充ListView。我自己多次实现了这一点,没有注意到任何 UI 性能问题。只需确保在后台线程中过滤您的收藏。 (AsyncTask 在这里派上用场)。

    最后一个提示:你有什么手机很旧吗?或者你认识的人会这样做?找到你能找到的最慢的手机,并在上面测试你的应用程序的性能。我自己有一个 HTC Legend,它已经过时而且速度很慢,但非常适合性能测试。如果它在我的(旧)手机上运行,​​它可以在任何手机上运行。

    如果您的应用程序流动,则为伪代码示例:

    public class FolderListActivity extends Activity implements OnItemSelected {
    
        // NOTE: THIS IS PSEUDO CODE
    
        private ListView listView
        private Adapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstaceState);
    
            // setContentView here 
            listView = (ListView)findViewById(R.id.your_listview_here);
            listView.setOnItemSelectedListener(this);
        }
    
        public class AsyncLoadMusicLocationTask extends AsyncTask<Void, Void, List<String>> {
    
            public List<String> doInBackground(Void... params) {
                // Load the information here, this happens in the background
                // using that cursor, i'm not sure what kind of things you are using
                // So I assumed a List of Strings
            }
    
            @Override
            public void onPostExecute(List<String> result) {
                // Here we have our collection that was retrieved in a background thread
                // This is on the UI thread
    
                // Create the listviews adapter here
                adapter = new Adapter(result, and other parameters);
                listView.setAdapter(adapter);
            }
        }
    
        @Override
        public void onItemSelect(Some params, not sure which) {
    
            // THIS SHOULD BE DONE ON THE BACKGROUND THE PREVENT UI PERFORMANCE ISSUES
    
            List<String> collection = adapter.getObjects();
            for (int i = 0; i < collection.size(); i++) {
                // Filter here
            }
    
    // this method will most probably not exist, so you will need to implement your own Adapter class
            adapter.setObjects(collections);
            adapter.notifyDataSetChanged();
        }
    }
    

    【讨论】:

    • 您好 Xtudio,感谢您的回答。如果我阅读正确,我的过程将是:加载应用程序,创建列表视图。用户选择文件夹,过滤列表内容并发送 notifyDataSetChanged,不调用光标适配器代码?这只会从列表视图中删除项目而不重新膨胀视图?至于性能,不幸的是我没有旧手机,但我想 ebay 可以派上用场!
    • 如果您已经拥有该集合,请使用循环或其他方式“手动”过滤此集合。 Android 中的光标并不是性能强大的野兽。
    • notifyDataSetChanged 将告诉适配器重建列表视图内容,但它仍然包含以前膨胀的视图。所以这是一个巨大的性能胜利。
    • 太好了,谢谢。我会阅读一下它是如何完成的,并将我的结果发布在这里!感谢您花时间帮助我,非常感谢。
    • 嗨,这对我正在做的事情来说非常正确。我让异步 doinbackground 完成查询媒体存储和抛出游标的繁重工作。 onPostExecute 将光标夹到光标适配器上。目前在我的应用程序中,每次用户选择一个新文件夹时,都会调用相同的 asynctask,它会通过光标适配器请求和扩展视图。所以,我需要做的是为每个点击事件检查数据是否是原始数据的子集,如果进行一些手动过滤然后通知数据集更改。如果没有,请调用原始 Async。太棒了,非常感谢
    猜你喜欢
    • 2012-11-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 2018-08-06
    相关资源
    最近更新 更多