[英]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。它基于反应和推送模型。
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.