Android: Is this just a custom ListView? - android

Feed in Four Square android app looks like this:
A rectangular box with actual post, below which is a Text like 10 people like this and so on.
Is this just a listView with Actual content having margins and a different background, and TextViews below it.
Because when i had a complicated ListView with an ImageView and 5-6 TextViews, it takes lot of time to load the UI.
1 of my friends who work on iOs said Instead of Custom ListView Items, use ImageView which look like a Custom View with images and textviews. Which makes loading lot faster. But ofcourse it takes lot to implement such thing.
I just want to know, if its just another custom listview?
And that my delay to load the UI is because of someother reason?
Such techniques are available in android too??
Thank You

Could be a ListView with complicated children views. Could also be an ExpandableListView.
There's a few reasons why it may load faster than something you've used before:
The images were probably already cached on the file system, so it loads from local storage rather than downloading the image.
The images were already the correct dimensions, so no resizing was needed.
Image loading was done on a background thread as to not lag the UI while images were being loaded into memory.

You could expand a complex layout for each ListView item in Adapter.getView() and remove (View.setVisibility(View.Gone)) on the views you don't need based on the item's object you want to render.
If you want to reuse the expanded layout don't forget to set the visibility of everithing again to View.VISIBLE.
I'm already doing this in my code:
if (post.getImageURL() != null && !post.getImageURL().isEmpty()) {
holder.image.setVisibility(View.VISIBLE);
holder.image.setScaleType(ScaleType.FIT_CENTER);
displayImage(post.getImageURL(), holder.image);
} else {
holder.image.setVisibility(View.GONE);
}
In this case I'm hidding an optional image.

Related

Android ListView with Custom Adapter, slow loading

I have a Custom Adapter for the ListView. The Layout has three images, some text. When loading the Listview, it takes a while, because of the images. Its something like Posts.
Same app in iOS is loading very fast, I think that UITableView works different than Listview.
Is there a way, in place to load all posts, only load for example 3 posts and when the user scrolls the Listview down, load the next 3, scroll down, load the next 3 and so on. This could give a better performance.
Normally, android listview work that way. Let's say there are 5 views that user can reach at the moment. ListView creates 9 views and when user scrolls it loads the bottom ones. You can think it this way. Your main problem is how are you loading your images and create the custom view. There is a common pattern for custom adapters which handles the fast recycling views(ViewHolder pattern). You should checkout the link for ViewHolder pattern. https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
It probably loads slow because the images should be resized every time, if you could save thumbnails it would go much faster.
Have you tried to use Recycler View instead? As long as I know using the Recycler View is the best practice nowadays. You can find a very good tutorial here:
http://www.vogella.com/tutorials/AndroidRecyclerView/article.html
You use the Recycler View almost the same way you do with List View: adapter, viewHolder, etc. It's good to mention though that you need to pay special attention to the use of the LayoutManager since the Recycler View it itself doesn't "know how to draw" the stuff on the screen.

How to display multiple Texts and Images in an item of RecyclerView or ListView?

I'm using a RecyclerView to display a list of data from server. The data contain text and an uncertain number of urls of images with HTML tag. For each item, I'm now using HTML.fromHTML() with a ImageGetter to parse the data, get images and display them in a TextView. However, the images in TextView cannot interact with user. Events on the images like click, magnifying and save are not supported by TextView. And I tried using a Webview instead, but its performance is poor.
I also tried to write a compound view which extends a LinearLayout, and add TextViews and ImageViews dynamically (the number of images for each item are not certain), but it behaved strangely in the RecyclerView.
Is there any better idea or should I improve my solutions forementioned?
Thanks in advance!
The solution has been found by myself with the help of other programmers on StackOverFlow. For those who may see this question, please check Android - Custom dynamically-generated compound View recreated in RecyclerView, causing poor performance.
The idea is simple, creating a CompoundView extending LinearLayout which adds TextViews and ImageViews dynamically based on the data attached. Note that the processes of creating views and setting data for the them are seperate. For other details, please check the url above.

best practice for updating an adapter

I have an adapter that displays a grid of thumbnails with a text. These thumbnails are heavy to load, heavy to draw, etc.
The thumbnail gridview is constantly filled with new content, let's say, 1 new item every 2 seconds.
My adapter has a function that I call from outside to inject new items:
public void postNew(Item i) {
arrayStuff.put(i);
notifyDataSetChanged();
}
What happens is, with my current approach, when I insert a new element in the gridview, it refreshes everything, even if the added item is not going to be visible. The refresh process kind of breaks the experience, specially if the user is browsing the gridview and new content arrives.
How would you recommend improving this? is there a lighter 'notifyDataSetChanged()' or something like that?
I do not know of any lighter version of notify data set, but you can always use ListView.getFirstVisiblePosition and ListView.getLastVisiblePosition to determine whether your latest added position is visible, and only call notifyDataSetChanged if it is.
As for "heavy" bitmaps, as heavy as it is I think you should resample or scale it to the minimum size you need, using LruCache you can reduce the need of re-drawing on notify data set changed.
It sounds like you probably need to implement some form of caching, it's not very good memory management to have images which are not visible loaded into memory, ideally you would retrieve them from cache when they become (or are about to become) visible.
An alternative approach could be to add some form of visual indicator when new content arrives and then implement "pull down to refresh" or similar, then make a call to notifyDataSetChanged() on your adapter to refresh the content. I can imagine that refreshing every couple of seconds would not give a great UX because it would be hard to follow if the screen content is constantly changing.
You need create custom view(dynamic at runtime) that adds multiple imageview and appropriate textview, the container view should be LinearLayout, after that you can able to update a particular view or element.

Out of memory error when nesting gridview inside listview

I'm trying to add a GridView of images (ImageView) for my android application. I've successfully implemented lazy loading and caching of images and all of my high quality images work flawlessly when I have a simple GridView. However, the problem occurs when I try to nest my GridView inside a ListView.
When I simply have a GridView, the app only has to keep reference to images that are currently being rendered on the screen. But when I nest a GridView of, say 100 hi-res images, inside a ListView, the app tries to keep a reference to all 100 images, when only 20 of them are being rendered on the screen at the time. I found this out through my Log output, where the app would print a message every time an image is "read". I would see the app read 20 images that are being displayed on the screen, but then it would keep going and read more images. When it reaches around 100~ images, the app would run out of memory and crash. This behavior does not happen when I have just the GridView; the app will just read 20 images, and load more as I scroll the screen.
How can I make it so that my ListView does not try to load all elements inside a child view (especially the one that's not being displayed on screen)?
Thanks!
EDIT:
For those wondering why I would want a GridView inside a ListView, it's because I'm trying to create something like this:
Except I'd like to have it in a ListView, as opposed to ExpandableListView.
You are getting this Exception because in an expanded GridView all the data is loaded in memory, if your data is too much it will cause OutOfMemory Exception.The solution is: divide your data in small parts and then try.
You can not nest scrollable Views in Android. Components such as ListView, GridView, ScrollView can't be nested into each other.
You should take a look at Fragments (http://developer.android.com/guide/components/fragments.html) and stop to re-think your UI a little bit.
And... for large datasets, image/data lazy-loading is not enough... it is highly recommended that you implement a paging mechanism that would allow the user to page trough the results/content.
Let's say you'll display 20 items at a time. You will have to add a Next and a Previous buttons on the sides of the GridView UI (or you can do it the cool way with gestures)... and tweak your GridView's Adapter logic to pull only 20 items from your Model or from the Server at a time.
I found a really simple implementation of paging with a grid view among my bookmarks: http://paulononaka.wordpress.com/2011/03/19/how-to-implement-a-paging-feature-in-android/ ... I bet there are better ways to do it, but it could give you ideas.
Good luck!

Change ImageView content within a GridView in Android

I am new to Android and Java. I am building an app that allows users to push a button which launches an image chooser where they can select from images on the sd card. The app loads with a grid view with 2 cells. One cell has an image view that has a default image. The other is the button. Once, the image is chosen, the image view needs to be displayed in the Image View of the Grid View.
I am using a string path that is being decoded from the images uri to create a bitmap. I then am calling imageView.setImageBitmap(bitmap). This is doing nothing. I have tried updating the image resource with a different image in the drawable folders and still nothing. I added a seperate image view just under the grid in my activity, and that image is updating fine which leads me to believe that this has to do with the grid view (this is my first grid view).
Any help is very much appreciated.
Thank you.
GridView is maybe not the right choice if you've only got two cells. You will probably have an easier time with a simple LinearLayout that has the two items you're dealing with.
But, here's how you do it with a GridView:
Create your adapter by extending BaseAdapter. The most important method is getView(), but it's where you should be doing the least amount of work.
When the GridView goes to redraw itself, it'll go through for each visible position and call getView() for each one. You'll be supplied a View. If the view is null, inflate a new one from your XML resources, populate it, and return it. If the view is NOT null, populate the existing one with the appropriate data. The widget is being efficient by recycling views.
The trick you need is that when you want the image to change, you need to call notifyDataSetChanged() on your adapter in order to trigger the redraw (which is when you'll populate the new image in the view for the appropriate cell).
That's the two-minute version. At Google I/O a year or two back, they did a talk on The World of ListView and posted it on YouTube. It was a good talk and pretty much everything there applies to GridView as well.

Categories

Resources