I have an android app that I'm developing using Xamarin. The app contacts the server and, via web service (SOAP), receives a list of objects. Currently, in my axml file I have just linear layout (ll) within scrollview tags and nothing else. In the code, I loop through the collection and new up the elements that I want and attach it to a layout. Once I'm done with each record, I attach (i.e.AddView) to the master layout (ll). Everything works.
I have a couple of concerns and I appreciate some feedback on it.
1) Each object in the list contains an URL to an image online. Currently, for each object, my process downloads the picture individually. Would ListView give me any advantage of reusing (caching , etc.) an already downloaded picture even though other attributes of the objects are different? Will there be any gain in terms of network utilization if I switch to ListView?
2) Is drawing elements by hand (like I'm doing) an acceptable best-practice?
Thanks all.
Definitely use a ListView. There is a great article here by Lucas Rocha that outlines exactly why ListViews are beneficial and how to make them perform even better. To give you a few examples, ListViews minimize the number of view inflations you do, and they only create the list items currently visible on the screen or about to become visible on the screen.
This is a huge improvement from your approach, since your current method would load every element in the list before presenting the activity to the user. Therefore, drawing elements by hand like you're currently doing is definitely not best-practice.
Also, for displaying images from URLs in your Xamarin app, I highly recommend that you use the Xamarin component UrlImageViewHelper. Despite being incredibly easy to implement in your app, it will improve performance drastically since it takes care of image caching and async image loading.
Related
This is not a code problem, I interpret the guidelines as that being OK.
I've been researching a way of building an infinitely scrolling calendar-like view in Android, but I've reached an impasse.
Right now my dilemma is that most of the similar views available have their children placed relative each other in a recurring style. With this I mean:
item 4 comes after item 3, which comes after item 2, and there is constant padding/margin between all items.
What I need is a way to produce an infinitely long scrollable view that may, or may not, contain items. The items should be placed at variable positions within the view. The best way I can describe a similar looking view is a one-day calendar-like view that is infinitely scrollable.
So far my best two bets are using the new RecyclerView with a custom LayoutManager (this seems very complex and still not perfectly documented by Google though). I like this approach because, among other things, it is optimized for displaying large sets in a limited view.
My other solution would be to build a completely custom View. However, with that solution I loose the adapter unless I build a container view (which is probably more complex than building a layout manager).
How would you go about solving such a problem? Tips are appreciated, I don't need code examples, just ideas which path is the best to solve this problem.
Thanks.
Apologies if I've misunderstood the guidelines
Edit: How I resolved this problem
My first solution to use RecyclerView with a special Decorator seemed promising, but it remained a "hack" so we decided not to go for that solution since we were afraid of the complications that it would create down the line.
To solve the problem I went with a SurfaceView instead of an Adapter, this means having to rewrite all the adapter-functionality for my SurfaceView but it seemed to be the best way of solving this issue of very custom drawing and layout managing for my use-case.
It still would be nice to build a custom Viewgroup that can handle this kind of layout problems.
ListView and ListAdapter are based on a fixed list, so the current infinite-scrollers just keep adding more and more data to the end of the list.
But what you want is scroller similar to Google's Calendar app which has a bi-directional infinite scroller. The problem with using ListView and ListAdapter in this case is that if you add data to the front of the list, the index of any one item changes so that the list jumps.
If you really start thinking about this from the MVC perspective, you realize that ListAdapter does not provide a model that fits this need.
Instead of having absolute indexing (i.e. 1, 2, 3, 4, etc), what you really want is relative indexing, so instead of saying "Give me the item at index 42" you want to say "here's an item, give me the five items before it". Or you have something like a calendar date which is absolute; yet — unlike your device's memory — it has effectively no beginning or end, so what you really want here is a "window" into a section of that data.
A better data model for this would be a kind of double-ended queue that is partly a LRU cache. You place a limit on the number of items in the structure. Then as prior items are loaded (user is scrolling up) the items at back end are pushed off, and when subsequent items are added (user is scrolling down), items at the front are pushed off.
Also, you would have a threshold where if you got within a few items of of one edge of the structure, a "loadNext" or "loadPrevious" event would fire and invoke a callback that you set up to push more data onto the edge of the structure.
So once you've figured out that your model is completely different, you realize that even RecyclerView isn't going to help you here because it's tied to the absolute indexing model. You need some sort of custom ViewGroup subclass that recycles item views like a ListView, but can adapt to the double-ended queue. And when you search code repos for something like this, there's nothing out there.
Sounds like fun. I'll post a link when I get a project started. (Sadly, it won't be done in any timely manner to help you right now, sorry.)
Something that might help you a little sooner: look at Google's Calendar implementation and see how they did it: Google Calendar Git repo
What you may be searching for is a FragmentStatePagerAdapter , where you can implement a swiped view, meaning when the user (for example)swipes to the right, a completely new view is displayed.
Using a FragmentStatePagerAdapter , you can handle a huge amount of views without overflowing the memory, because this specific PagerAdapter only keeps the views' states and is explicitly meant to handle large sets of views.
Keeping your example of a calendar, you can implement swiped navigation between for example weeks and generate the week views on demand while only keeping for example the year and the week's number as identifiers.
There are plenty of online tutorials for Android, maybe you have a look at this one
I'm working on an app right now displaying a contact list. The app is for Android and iOS, developed in AS3. That contact list contains on a basic usage 1000 items and that could go to 10 000.
Now a displayList with that many items does not work of course.
So I tried using BitmapData (the same item is updated, moved, and "stamped" on the BitmapData) before rendering but again, that's too big for a bitmapData.
I am now thinking about calculating the position of the scroll in the contact list and render on the displayList only what's on screen but I'm not sure how to handle this.
What are the best practices for that kind of issue?
Thanks
I am now thinking about calculating the position of the scroll in the
contact list and render on the displayList only what's on screen but
I'm not sure how to handle this.
That's the correct way to do it, it's a form of object pooling and I think it's also known as layout virtualization. I don't know how to do it in classic AS, but I've been using the Starling framework (gpu rendered display list), and the components lib there (known as Feathers), has such a list, you may wish to check its implementation. Here's a demo (check the List), I've tested this with thousands of items and it works perfectly:
Feathers Component Explorer
But in short the idea is to create visual components equal to the maximum that can be seen at the same time. Then, whenever the list moves you must check which are the visible indexes. When they change, which happens when an item becomes invisible - for example going off the top, you move it to the bottom and reuse it with new data, corresponding to its index.
It's best to use some framework for that - search for UI tools. If you are using Starling - there is Feathers. Also you can use MadComponents which is pretty nice. For simple cases you can use MinimalComponents.
They all have built in lists. If you don't like them, you should build one by yourself.
The best practice is to show only the visible items, and have others removed from stage. So you have to calculate the current position of the list that is being scrolled, calculate the items that are visible, and then add them and display them. Everything else should be removed and hidden.
But again, I think some of those I mentioned should fit your needs.
I am comparing performances, specifically scrolling speeds of a ListView, of apps that I create, to native Android 4.0 apps - Gmail, Gtalk, etc.
One thing I have noticed is that the scrolling frame rate of a ListView on the native Android apps are very high - almost 60fps. In my apps, a ListView don't scroll nearly as fast.
Assuming I'm using ListView incorrectly (which I'm not - I've followed everything stated here: http://www.youtube.com/watch?v=wDBM6wVEO70), I decided to create a dummy ListView that just returns a dozen almost empty LinearLayout views as it's rows (yes I'm using convertView correctly). What's disturbing here is that my almost blank ListView has slower scrolling performance than any of the native apps - Gmail, Gtalk, Contacts, etc.
As a side note, a simple ScrollView has really good scrolling performance, but it is inadvisable to use a ScrollView for large lists.
Clearly, the native apps are doing something (or have access to something) that I don't understand. Unfortunately these native apps aren't open source. Does anyone have any insight as to how these native apps achieve such tremendous performance?
After look at the source code for the native email application, I have found that the list items in a list of messages are single Views, not ViewGroups like LinearLayout. That makes for a very flat View hierarchy which leads to a better frame rate while scrolling the list. I think I remember watching a video of a talk by Romain Guy (one of the lead Android UI engineers) that mentioned that the Gmail team did something similar to increase performance.
To achieve this yourself, you'd have to subclass View and draw everything in the View yourself in the onDraw() method.
Here is the source for a message list item in the current email application.
They do a cool trick where you inflate a view (but don't attach it), get the coordinates of where the items go based on the ViewGroup it is in, and cache the coordinates in a Map so when a view is recycled in a list you don't have to inflate that view again. I might try this in a future project of mine!
I hope this helps!
There are some techniques to make ListView faster: caching and using dissapeared list items as new list items to avoid long operation of creating them. You need to create your own class based on ListView to realize these techniques. Read more here.
I also followed on that video to build my list view. In my app, there are not much items (rows). But I think if we just do as the video said, we are on right way, at least on the theory?
I need some valuable advice from you guys...
I have a UI where I have to drag objects from one view to another.
I have a rough sketch of this UI below
I think I have to create a custom view for this. I have to drag a square and a ball from bag 1 and bag2 [both bags are scrollable, can contain 10 to 60 items each] and drop it to the closet one by one. and later I have to find the number of items in the closet. The items in the closet must be arranged in a well maintained fashion [may be ...like 6 in a row].
Where should I start?
How many custom views should I use?
Is there a simple and effective UI solution for this?
Happy coding..!
I would suggest a design with three different GridView objects laid out inside a ViewGroup that supports dragging objects from one GridView to another. The objects would be custom ImageView subclasses so you'd have a place in code to support a drag-and-drop protocol of some sort and because you'd likely want to associate some data that is specific to your application with the objects being dragged.
As for the drag-and-drop protocol, you could consider an adaptation of the Android Launcher drag-and-drop framework or the current drag-drop classes described on the Android developers' website. I don't have much to say about the current drag-drop classes. I have not tried them yet, but understanding them is on my to-do list. However, I have done an adaptation of the Launcher code, and I have written it up on my blog and posted demo apps and source code there. See Drag-Drop for an Android GridView.
With the framework that originated in the Android Launcher, you have a good set of classes and interfaces to work with. Some of the objects include: DragLayer, DragSource, DropTarget, DragController, DragView. The DragLayer is a custom ViewGroup within which all drag-drop operations occur. It delegates handling of all the touch events to a DragController, which is the object that does the actual moving of objects around on the screen. As it does so, it interacts with DropTarget objects to give the user visual feedback that something is being dragged and that a place to drop something is available. A DropTarget is an object where something can be dropped. A DragSource is the interface for objects that can be dragged within the DragLayer. The Launcher framework is a good one because it gives you a way to think about dragging and dropping and how you want to divide up the responsibilities defined by the framework.
The reason I suggest GridViews for your problem is it sounds like you are thinking that way already. The closet has "maybe 6 in a row" so that could be a GridView with one or more rows depending on how screen space you have. A GridView would also work for the container that holds the squares and circles. If that is a good fit, you could study the code in my drag-drop tutorial and see if that makes it easy for you to move objects from one GridView to another.
In my demo program, I ended up with a custom subclass of ImageView that I called an ImageCell. These are views that are on the grid. An ImageCell allows objects to be dragged from them and onto them. For awhile as I worked on the tutorial, I had a custom GridView class too but ended up with the standard GridView. It sounds like you'd want a custom GridView because it sounds like being in the closet is different than being in the other sections. Having it gives you a convenient place for the methods you have not thought of yet.
I hope some of these suggestions prove useful.
Depends on the Android version you are targeting. For 11 and above you can use the built in drag and drop functionality, otherwise you are pretty much on your own. I would normally advice you to implement some sort of a long press action that might even allow you to select multiple items and move them in batches, which would be a really simple thing to implement.
If you really need DnD you should check out this example, it should give you some idea on how to make your own implementation.
I think that bag1, bag2 and closet can be three instance of the same configurable custom view (let's name it CustomBagView).
CustomBagViews should be responsible for displaying items (using a gridview of imageview for example).
I think those will not need to handle drag & drop directly but they should support
removing and adding elements
provide a setOnItemTouched(Interface_class) callback setter.
Then you will need to code a Container custom view (let's name it BagContainerView) that will contain the three bags and handle the dragging & dropping from the bags.
You will provide a handleDrag callback to each bag using CustomBagView.setOnItemTouched, then track the finger motion in it.
When the dragging finishes, you must find where it ends, locate the right 'customBagView' and ask it to add the item to its list.
Building a dictionary application I need a ListView that shows over 100k items. I want to let the user scroll as much as needed.
What's the best practice for searching and showing words?
Is it ok to show 150,000 words in the ListView (for pereformance)?
If not how to add 100 other words after the user reaches to the end of the list?
Currently I show 50 words previous and 50 words next of searched word.
Thank you.
(second answer in response to clarification about performance)
There are different ways to do this based on where your data is.
The best way is to have your data in a sqlite database and use a CursorAdapter. Android then manages the fetching of your data and won't fetch data that isn't currently being shown on the screen.
If your words are in an array in memory, try ArrayAdapter or SimpleAdapter.
The Adapter interface, from which all of the above classes inherit, is designed to provide good ListView performance regardless of the number of objects in the list.
One built-in way to allow fast scrolling is via the fast scroll thumb. In your xml, set:
android:fastScrollEnabled="true"
on your ListView, or try:
listView.setFastScrollEnabled(true)
listView.setFastScrollAlwaysVisible(true)
RecyclerView is very good for this. I have developed an open source library especially designed to scroll through large list with extreme speed. In fact it can move well in excess of 1000 items per second both in single and multiple column layouts You can check out the repo here: https://bitbucket.org/warwick/hgfastlist or you can checkout the OpenGL version here: https://bitbucket.org/warwick/hgglfastlist. Here is a demo video on Youtube: https://www.youtube.com/watch?v=oz7aeAlOHBA&feature=youtu.be
Even if you don't want to use this library, there's loads of code to read through in the demo app that will give you good ideas.