简体   繁体   English

如何在不冻结程序的情况下更新ListView

[英]How to update ListView without freezing the program

So I have a list of strings (ISBNs), and I need to fill a listview with the objects (Book objects) associated with these strings . 所以我有一个strings列表(ISBN),我需要用与这些strings相关联的对象(Book对象)填充listview The problem is that the function I have to get the Book object using the string takes time, and so to get, say 30 books, the wait approaches 4 or 5 seconds. 问题是我必须使用字符串获取Book对象的函数需要时间,因此要获得30本书,等待接近4或5秒。

One approach I've thought of is to get the Book objects one at a time, and to add them to the list as I get them. 我想到的一种方法是一次获取一个Book对象,并在我得到它们时将它们添加到列表中。 But this process will freeze the UI until it's done adding them all. 但是这个过程会冻结UI直到完成所有这些操作。 If I try to put this process in a new thread, it won't let me add to the any UI objects (since it's from another thread). 如果我尝试将此进程放在一个新线程中,它将不会让我添加到任何UI对象(因为它来自另一个线程)。 If I try to put it in an AsyncTask , I can't access the ListView since it's in the MainActivity class. 如果我尝试将它放在AsyncTask ,我就无法访问ListView因为它位于MainActivity类中。

There must be a way to dynamically update a UI element, I'm sure I've seen it done. 必须有一种动态更新UI元素的方法,我相信我已经看过它了。 Any suggestions? 有什么建议么?

EDIT : 编辑

This is the code I'm using to actually add items to the list: 这是我用来实际添加项目到列表的代码:

//List view and adapter setup
listView = (ListView) findViewById(R.id.listViewCheckout);
bookAdapter = new SearchBookAdapter(getApplicationContext(), R.layout.search_row_layout);
listView.setAdapter(bookAdapter);

for(int i = 0; i < searches.size(); i++) {

    //Get the book
    Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));

    //Assign data to the adapter variables
    Bitmap cover = book.getCover();
    String title = book.getTitle();
    String author = book.getAuthor();

    //Add data to the adapter and set the list
    SearchBookDataProvider dataProvider = new SearchBookDataProvider(cover, title, author);
    bookAdapter.add(dataProvider);
    bookAdapter.notifyDataSetChanged();
}

Can you make some changes to your code like this it simple it think it will work 您是否可以对代码进行一些更改,它认为它可以正常工作

//List view and adapter setup
listView = (ListView) findViewById(R.id.listViewCheckout);
bookAdapter = new SearchBookAdapter(getApplicationContext(), R.layout.search_row_layout);
SearchBookDataProvider dataProvider;
listView.setAdapter(bookAdapter);

 new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] objects) {
                for(int i = 0; i < searches.size(); i++) {

                //Get the book
                Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));

                //Assign data to the adapter variables
                Bitmap cover = book.getCover();
                String title = book.getTitle();
                String author = book.getAuthor();

                //Add data to the adapter and set the list
                dataProvider = new SearchBookDataProvider(cover, title, author);
                bookAdapter.add(dataProvider);
                }
            }
            @Override
            protected void onPostExecute(Object o) {
                if (bookAdapter!= null) {
                    bookAdapter.notifyDataSetChanged();
                }
                super.onPostExecute(o);
            }
 }.execute();

you can use TimerTask to update the listview or runUiThread() or doInBackground(). 您可以使用TimerTask更新listview或runUiThread()或doInBackground()。 But remember should use notifysetChanges() when you update the list. 但是请记住在更新列表时应该使用notifysetChanges()

Step 1: Declare a Executer service 第1步:声明Executer服务

 private ExecutorService mExecuterService = null;

Step 2:Declare a class for your list iteration and view update 第2步:为列表迭代声明一个类并查看更新

  class ListViewUpdater implements Runnable{

            public ListViewUpdater(/* if you need you can pass list params here */){

            }

            @Override
            public void run() {
                for(int i = 0; i < searches.size(); i++) {

                    //Get the book
                    Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));

                    //Assign data to the adapter variables
                    Bitmap cover = book.getCover();
                    String title = book.getTitle();
                    String author = book.getAuthor();



                }
//below code is important for Updating UI ,you should run UI Updates in UI thread
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        bookAdapter.notifyDataSetChanged();
                    }
                });
            }
        }

Step 3: Initilize and call below methods 第3步:初始化并调用以下方法

//Add data to the adapter and set the list
    SearchBookDataProvider dataProvider = new SearchBookDataProvider(cover, title, author);
   bookAdapter.add(dataProvider);
    mExecuterService = Executors.newSingleThreadExecutor()
    mExecuterService.execute(new ListViewUpdater());

It may solve your problems. 它可以解决你的问题。

I think if you are open to use a open source project ,then my suggestion will be use RX-JAVA.Which is based in reactive and push based model. 我想如果您愿意使用开源项目,那么我的建议将是使用RX-JAVA。它基于反应和推送模型。

link for rx-java . rx-java的链接

rx-java example . rx-java示例

You can get the list of the books in a Thread and send a Broadcast with the data received. 您可以获取线程中的书籍列表,并使用收到的数据发送广播。 Register a broadcast receiver in your MainActivity class and update the Adapter in the receiver. 在MainActivity类中注册广播接收器并更新接收器中的适配器。 That should not freeze the UI. 这不应该冻结UI。

EDIT - 编辑 -

  BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        Book book = (Book)intent.getSerializableExtra("Book");
        SearchBookDataProvider dataProvider = new SearchBookDataProvider(cover, title, author);
        bookAdapter.add(dataProvider);
        bookAdapter.notifyDataSetChanged();
    }
};

Thread thread = new Thread(){
    @Override
    public void run()
    {
        for(int i = 0; i < searches.size(); i++) {

            //Get the book
            Book book = BackendFunctions.getBookFromISBN(fbSnapshot, searches.get(i));

            Intent intent = new Intent();
            intent.setAction("Book Received");
            intent.putExtra("Book",book);
            sendBroadcast(intent);
        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (ListView) findViewById(R.id.listView);
    listView.setAdapter(bookAdapter);
    registerReceiver(broadcastReceiver,new IntentFilter("Book Received"));
    thread.start();

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在不冻结应用程序的情况下更新 TextView - Update TextView without Freezing Application 延迟后如何更新ImageView(图像)而不冻结UI并允许用户单击? - How to update ImageView (images) after a delay without freezing UI and allowing user clicks? 搜索算法(DFS,BFS,A star等)。 如何在没有“冻结”的情况下更新GUI(具有更新状态)? - Search algorithms (DFS,BFS,A star etc.). How to update the GUI (with updated state) without “freezing”? 如何在不冻结的情况下以相同的方法运行2个线程? - How to run 2 threads in the same method without it freezing? 如何在不冻结GUI的情况下调用SwingWorker .get()? - How to call SwingWorker .get() without freezing GUI? 如何在不冻结我的应用程序的情况下运行循环? - How to run loop without freezing my app? JButton Action Listener进度栏,是否更新而不冻结? - JButton Action Listener progress bar, update without freezing? 如何在没有初始动画的情况下更新 ListView 中的 SpeedView? - How to update SpeedView inside ListView without initial animation? 如何在不创建新适配器等的情况下更新ListView中的ListItem - How to update ListItems in ListView without creating a new Adapter etc 更新ListView而不清除和闪烁 - Update ListView without clearing and blinking
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM