Android NSFetchedResultsController - android

I have an iPhone and an Android app. On iPhone I use NSFetchedResultsController to manage the data I have for my UITableView's. Currently I have a lot of data (several thousands of rows).
On my Android app i'm using ORMLite and i'm storing the data into a table, but when I fetch, i'm pulling out all data into an array and using ArrayAdapters. Is there a more efficient way to do this such as an NSFetchedResultsController type object? I want to only load the objects needed, rather than all of them for performance reasons.
Is there a way to do this within ORMLite? I tried to find in the documentation but found nothing so far... Is there anything else I'm missing that would be of help here?

You could use CursorAdapter.
See http://developer.android.com/reference/android/widget/CursorAdapter.html
and http://www.mysamplecode.com/2012/07/android-listview-cursoradapter-sqlite.html
or you could implement an Endless Adapter
Lazy Loading might help here.
Lets presume you have a data of 10000 entries. You could display a finite subset of this say 90 entries at a time.You could initially load a few entries say 30(1-30). On scrolling to the end you load 30 more entries.As soon as the no.of entries loaded reaches 90 (on the third load) you could truncate the current dataset as 31-120 instead of the previous 1-90.
The same goes the other way too i.e on scrolling upwards.
int offset=0;
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
final int MAX_SUBSET=90;
final int INTERVAL=30;
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
final int lastItem = firstVisibleItem + visibleItemCount;
if(lastItem == totalItemCount) {
//Load new data and update The adapter.
if(totalItemCount<=MAX_SUBSET){
loadData(0,totalItemCount+INTERVAL);
}
else{
offset+=INTERVAL;
loadData(offset,MAX_SUBSET);
}
}
else if(0==firstVisibleItem){
//Load old data
if(totalItemCount<=MAX_SUBSET){
loadData(0,totalItemCount+INTERVAL);
}
else{
offset-=INTERVAL;
loadData(offset,MAX_SUBSET);
}
}
});
Ps: I have missed out a few boundary checks but hope you get the general idea.

Related

What is the correct way in android to load images from URL in a ListView without delay

I have to show a list of posts, some of them with images (think in something like twitter) and load more when I do scroll on the ListView but images take some seconds to appear. How can I do the load without delay? Currently I'm doing it with Picasso
Here my code:
ListView lv = findViewById(R.id.list_feed);
arrayPosts = fillArray(data);
adapter= new PostAdapter(this, arrayPosts);
lv.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
int lastIndexInScreen = visibleItemCount + firstVisibleItem;
if (lastIndexInScreen >= totalItemCount && totalItemCount > 0 && !isLoading) {
isLoading = true;
loadMore();
}
}
});
lv.setAdapter(adapter);
My Adapter's getView() method:
public View getView(int i, View view, ViewGroup viewGroup) {
Post post = (Post) getItem(i);
view = LayoutInflater.from(context).inflate(R.layout.row_post_item, null);
(...)
Picasso.with(context).load(post.getImgProfile()).into(imgProfile);
Picasso.with(context).load(post.getImagePost()).into(imgPost);
(...)
return view;
}
You can't do it with no delay at all. The download speed depends on Internet connection & the device, so some delay has to exist, unless you pre-load images one page up front in advance (that's how most apps do it). But even then fast scrolling may cause some delay.
I would suggest Glide.
It is much faster than Picasso. It handles the download to memory and cache utilization better than Picasso. It acts better with GIFs, and prevents nasty OutOfMemoryError. Of course you can load placeholders until your image loads etc.
It even comes recommended by Google.
Cheers
Picasso is a very good way to load images because of its caching abilities , still I would recommend you read this answer and then decide which option you want to use according to your specific needs.

Android - load more items when grid view has reached the end

I'm making an app and I'm using grid view to show all of my images, the problem is I have lots of images, about 12,000, and I don't want to load all of them at the start, because lets face it, it will take forever, so I was wondering what is the best way of accessing the server to fetch more items once the gridview has reached the end.
Thanks.
To achieve load more items on scrolled to end of the gridview
gridView.setOnScrollListener(new AbsListView.OnScrollListener(){
#Override
public void onScroll(AbsListView view,
int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
//Algorithm to check if the last item is visible or not
final int lastItem = firstVisibleItem + visibleItemCount;
if(lastItem == totalItemCount){
// here you have reached end of list, load more data
fetchMoreItems();
}
}
#Override
public void onScrollStateChanged(AbsListView view,int scrollState) {
//blank, not required in your case
}
});
One way is to start the server request for an image in the adapter getView(). When the request completes, you set the retrieved bitmap on the ImageView. There is a very in-depth description of this technique on the Android Developer Blog: Multithreading For Performance | Android Developers Blog. Most servers are fast enough that the lag time to display the image is not objectionable.
However, if you want to load images before the ImageViews are displayed, here's another way you can do it with an OnScrollListener, an AsyncTask, and a list adapter for the `GridView.
Say you have a constant final int THRESHOLD = 50; and a variable lastItem that starts at zero.
When user displays your GridView the AsyncTask kicks off and retrieves the first 100 images. In the onPostExecute(), it adds the images to your adapter and calls notifyDataSetChanged(). It also adds 100 to lastItem.
So now your adapter has 100 images. The user is scrolling through images and the OnScrollListener gets called.
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
if (firstVisibleItem >= lastItem - THRESHOLD) {
new FetchImageAsyncTask().execute();
}
}
Your AsyncTask executes, lastItem is updated to 200, and your adapter gets 100 more images.
Then the user scrolls some more and it starts all over again.
By using the threshold, the user can scroll another 50 images before the end of the list, and that may be enough time to load the next 100 images.

How to understand firstVisibleItem and visibleItemCount in onScroll method?

I have gridview listing 9 items per page, and when user scrolls it should load 9 more. But i cannot set it properly, i am struggling with this code:
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if((firstVisibleItem + visibleItemCount) == totalItemCount)
{
load_more();
}
}
});
I am not sure what to put on calculation line, so to give me 9 by 9 as user scrolls. I tried different calculations, but without success, sometimes it just loads automatically couple of times, sometimes infinite. How to accomplish what I need?
There is a nice library which exactly does what you need.
https://github.com/shontauro/android-pulltorefresh-and-loadmore
Sample
((LoadMoreListView) getListView())
.setOnLoadMoreListener(new OnLoadMoreListener() {
public void onLoadMore() {
// Do the work to load more items at the end of list here
}
});
There are more options available in the library, you can try that as well.
For actually implementing for yourself, its quite difficult to do on onScroll. I too gave up and implemented through different procedure.

Loaders with Paginated Listview

I am using Loader implementation with AsynTaskLoader and Matrixcursor. Also implemented paginated listview. When user scrolls, I get to use restartloader function; yet it discards the current data and restarts loading the whole list and reloads them all over again.
Getting the data by using LIMIT keyword of SQL. Everytime I use reload function LIMIT value is increased by 10. Thus, everytime I use the restartloader function, it discards all it has and reloads what discarded and another 10.
I feel like I could add up to the current matrixcursor. Is this bad implementation? Is there any better way to do this? Thanks in advance.
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount != 0) {
getSupportLoaderManager().restartLoader(0, loadMoreItemsToList(), callbacks);
}
}
Here is the loadMoreItemsToList function:
Bundle loadMoreItemsToList(){
isLoadingItems = true;
itemCountInList += 10;
bundle.putInt("ItemCount", itemCountInList);
return bundle;
}

Binding onScrolling listener to the android ListView

just wanted to ask is there a possibility to bind some listener to the ListView scroll event.
What I would like to achieve is that once ListView have been scrolled to the bottom I would like to ask server for more data if any is there.
I know that there is a function like: getLastVisiblePosition() but I assume it must bu used in some kind of listener in order to compare with currently last visible position, am I right ?
cheers,
/Marcin
Just to extrapolate on TomTo's answer, some thoughts on how you might do this (theoretical, I haven't tried this in practice):
ListView lv = (ListView)findViewById(R.id.list_view);
lv.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//Check if the last view is visible
if (++firstVisibleItem + visibleItemCount > totalItemCount) {
//load more content
}
}
});
Since firstVisibleItem is returns an index (0-based), I increment by one to get the actual item number. Then, if that, plus the number of visible items, is greater than the total number of items, then in theory the last view should be visible. Shouldn't be a problem, but keep in mind this isn't called till the scrolling is finished.
used
if (++visibleItemCount > totalItemCount)
instead
if (++firstVisibleItem + visibleItemCount > totalItemCount)
AbsListView.OnScrollListener ?

Categories

Resources