所以我有一个strings
(ISBN)列表,我需要用listview
填充与这些strings
相关联的对象(书籍对象)。问题是我必须使用字符串获取Book对象的函数需要时间,因此要获得30本书,等待接近4或5秒。
我想到的一种方法是一次获取一个Book对象,并在我得到它们时将它们添加到列表中。但是这个过程会冻结UI
,直到完成所有这些操作。如果我尝试将此进程放在一个新线程中,它将不允许我添加到任何UI
对象(因为它来自另一个线程)。如果我尝试将其放入AsyncTask
,我无法访问ListView
,因为它位于MainActivity
类中。
必须有一种动态更新UI
元素的方法,我相信我已经看过它了。有什么建议吗?
编辑:
这是我用来实际向列表中添加项目的代码:
//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();
}
答案 0 :(得分:1)
您是否可以对代码进行一些更改,它认为它可以正常工作
//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();
答案 1 :(得分:0)
您可以使用 TimerTask 来更新listview或runUiThread()或doInBackground()。但是,请记住在更新列表时应使用 notifysetChanges() 。
答案 2 :(得分:0)
第1步:声明Executer服务
private ExecutorService mExecuterService = null;
第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();
}
});
}
}
第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());
它可以解决你的问题。
答案 3 :(得分:0)
答案 4 :(得分:-1)
您可以获取线程中的书籍列表,并使用收到的数据发送广播。 在MainActivity类中注册广播接收器并更新接收器中的适配器。这不应该冻结用户界面。
编辑 -
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();
}