diff --git a/src/org/geometerplus/android/fbreader/BookmarksActivity.java b/src/org/geometerplus/android/fbreader/BookmarksActivity.java index cc1515028..14c8bfbff 100644 --- a/src/org/geometerplus/android/fbreader/BookmarksActivity.java +++ b/src/org/geometerplus/android/fbreader/BookmarksActivity.java @@ -44,15 +44,17 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte private static final int DELETE_ITEM_ID = 2; private final BookCollectionShadow myCollection = new BookCollectionShadow(); + private volatile Book myBook; - private List myAllBooksBookmarks; - private final List myThisBookBookmarks = new LinkedList(); - private final List mySearchResults = new LinkedList(); + private final Comparator myComparator = new Bookmark.ByTimeComparator(); private ListView myThisBookView; - private ListView myAllBooksView; private ListView mySearchResultsView; + private volatile BookmarksAdapter myThisBookAdapter; + private volatile BookmarksAdapter myAllBooksAdapter; + private volatile BookmarksAdapter mySearchResultsAdapter; + private final ZLResource myResource = ZLResource.resource("bookmarksView"); private final ZLStringOption myBookmarkSearchPatternOption = new ZLStringOption("BookmarkSearch", "Pattern", ""); @@ -78,31 +80,34 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte final TabHost host = getTabHost(); LayoutInflater.from(this).inflate(R.layout.bookmarks, host.getTabContentView(), true); + + myBook = SerializerUtil.deserializeBook(getIntent().getStringExtra(FBReader.BOOK_KEY)); } - private void init() { - myAllBooksBookmarks = new ArrayList(myCollection.bookmarks(0, 100000)); - Collections.sort(myAllBooksBookmarks, new Bookmark.ByTimeComparator()); + private class Initializer implements Runnable { + public void run() { + long id = 0; + while (true) { + final List allBookmarks = myCollection.bookmarks(id, 20); + if (allBookmarks.isEmpty()) { + break; + } else { + id = allBookmarks.get(allBookmarks.size() - 1).getId() + 1; + } - final Book book = SerializerUtil.deserializeBook(getIntent().getStringExtra(FBReader.BOOK_KEY)); - if (book != null) { - final long bookId = book.getId(); - for (Bookmark bm : myAllBooksBookmarks) { - if (bm.getBookId() == bookId) { - myThisBookBookmarks.add(bm); + myAllBooksAdapter.addAll(allBookmarks); + if (myBook != null) { + final List thisBookBookmarks = new LinkedList(); + final long bookId = myBook.getId(); + for (Bookmark b : allBookmarks) { + if (b.getBookId() == bookId) { + thisBookBookmarks.add(b); + } + } + myThisBookAdapter.addAll(thisBookBookmarks); } } - - myThisBookView = createTab("thisBook", R.id.this_book); - new BookmarksAdapter(myThisBookView, myThisBookBookmarks, true); - } else { - findViewById(R.id.this_book).setVisibility(View.GONE); } - - myAllBooksView = createTab("allBooks", R.id.all_books); - new BookmarksAdapter(myAllBooksView, myAllBooksBookmarks, false); - - findViewById(R.id.search_results).setVisibility(View.GONE); } @Override @@ -111,9 +116,22 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte myCollection.bindToService(this, new Runnable() { public void run() { - if (myAllBooksBookmarks == null) { - init(); + if (myAllBooksAdapter != null) { + return; } + + if (myBook != null) { + myThisBookView = createTab("thisBook", R.id.this_book); + myThisBookAdapter = new BookmarksAdapter(myThisBookView, true); + } else { + findViewById(R.id.this_book).setVisibility(View.GONE); + } + myAllBooksAdapter = new BookmarksAdapter(createTab("allBooks", R.id.all_books), false); + findViewById(R.id.search_results).setVisibility(View.GONE); + + final Thread initializer = new Thread(new Initializer()); + initializer.setPriority((Thread.MIN_PRIORITY + Thread.NORM_PRIORITY) / 2); + initializer.start(); } }); @@ -132,7 +150,7 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte final LinkedList bookmarks = new LinkedList(); pattern = pattern.toLowerCase(); - for (Bookmark b : myAllBooksBookmarks) { + for (Bookmark b : myAllBooksAdapter.bookmarks()) { if (MiscUtil.matchesIgnoreCase(b.getText(), pattern)) { bookmarks.add(b); } @@ -171,13 +189,13 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte void showSearchResultsTab(LinkedList results) { if (mySearchResultsView == null) { mySearchResultsView = createTab("found", R.id.search_results); - new BookmarksAdapter(mySearchResultsView, mySearchResults, false); + mySearchResultsAdapter = new BookmarksAdapter(mySearchResultsView, false); } else { - mySearchResults.clear(); + mySearchResultsAdapter.clear(); + } + for (Bookmark b : results) { + mySearchResultsAdapter.add(b); } - mySearchResults.addAll(results); - mySearchResultsView.invalidateViews(); - mySearchResultsView.requestLayout(); getTabHost().setCurrentTabByTag("found"); } @@ -190,17 +208,6 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte } } - private void invalidateAllViews() { - myThisBookView.invalidateViews(); - myThisBookView.requestLayout(); - myAllBooksView.invalidateViews(); - myAllBooksView.requestLayout(); - if (mySearchResultsView != null) { - mySearchResultsView.invalidateViews(); - mySearchResultsView.requestLayout(); - } - } - @Override public boolean onContextItemSelected(MenuItem item) { final int position = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).position; @@ -217,10 +224,15 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte return true; case DELETE_ITEM_ID: myCollection.deleteBookmark(bookmark); - myThisBookBookmarks.remove(bookmark); - myAllBooksBookmarks.remove(bookmark); - mySearchResults.remove(bookmark); - invalidateAllViews(); + if (myThisBookAdapter != null) { + myThisBookAdapter.remove(bookmark); + } + if (myAllBooksAdapter != null) { + myAllBooksAdapter.remove(bookmark); + } + if (mySearchResultsAdapter != null) { + mySearchResultsAdapter.remove(bookmark); + } return true; } return super.onContextItemSelected(item); @@ -231,9 +243,8 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte SerializerUtil.deserializeBookmark(getIntent().getStringExtra(FBReader.BOOKMARK_KEY)); if (bookmark != null) { myCollection.saveBookmark(bookmark); - myThisBookBookmarks.add(0, bookmark); - myAllBooksBookmarks.add(0, bookmark); - invalidateAllViews(); + myThisBookAdapter.add(bookmark); + myAllBooksAdapter.add(bookmark); } } @@ -249,17 +260,69 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte } private final class BookmarksAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, View.OnCreateContextMenuListener { - private final List myBookmarks; - private final boolean myCurrentBook; + private final List myBookmarks = + Collections.synchronizedList(new LinkedList()); + private final boolean myShowAddBookmarkItem; - BookmarksAdapter(ListView listView, List bookmarks, boolean currentBook) { - myBookmarks = bookmarks; - myCurrentBook = currentBook; + BookmarksAdapter(ListView listView, boolean showAddBookmarkItem) { + myShowAddBookmarkItem = showAddBookmarkItem; listView.setAdapter(this); listView.setOnItemClickListener(this); listView.setOnCreateContextMenuListener(this); } + public List bookmarks() { + return Collections.unmodifiableList(myBookmarks); + } + + public void addAll(final List bookmarks) { + runOnUiThread(new Runnable() { + public void run() { + synchronized (myBookmarks) { + for (Bookmark b : bookmarks) { + final int position = Collections.binarySearch(myBookmarks, b, myComparator); + if (position < 0) { + myBookmarks.add(- position - 1, b); + } + } + } + notifyDataSetChanged(); + } + }); + } + + public void add(final Bookmark b) { + runOnUiThread(new Runnable() { + public void run() { + synchronized (myBookmarks) { + final int position = Collections.binarySearch(myBookmarks, b, myComparator); + if (position < 0) { + myBookmarks.add(- position - 1, b); + } + } + notifyDataSetChanged(); + } + }); + } + + public void remove(final Bookmark b) { + runOnUiThread(new Runnable() { + public void run() { + myBookmarks.remove(b); + notifyDataSetChanged(); + } + }); + } + + public void clear() { + runOnUiThread(new Runnable() { + public void run() { + myBookmarks.clear(); + notifyDataSetChanged(); + } + }); + } + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position; if (getItem(position) != null) { @@ -286,7 +349,7 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte } else { imageView.setVisibility(View.GONE); textView.setText(bookmark.getText()); - if (myCurrentBook) { + if (myShowAddBookmarkItem) { bookTitleView.setVisibility(View.GONE); } else { bookTitleView.setVisibility(View.VISIBLE); @@ -309,14 +372,14 @@ public class BookmarksActivity extends TabActivity implements MenuItem.OnMenuIte } public final Bookmark getItem(int position) { - if (myCurrentBook) { + if (myShowAddBookmarkItem) { --position; } return (position >= 0) ? myBookmarks.get(position) : null; } public final int getCount() { - return myCurrentBook ? myBookmarks.size() + 1 : myBookmarks.size(); + return myShowAddBookmarkItem ? myBookmarks.size() + 1 : myBookmarks.size(); } public final void onItemClick(AdapterView parent, View view, int position, long id) {