Best practice on connecting Activities - android

I'm writing my first Android app and want to pick up good coding practices. I have an Activity which contains a 2-column grid of all the data items available in the app (listActivity). There's an Activity to create a new data item (createActivity), which is triggered from the listActivity. Now, when the createActivity finishes, what is the best way to handle this situation with respect to the following:
Should the createActivity store the new data item in the permanent storage and return only the ID of the newly created item to the listActivity OR should it return all the data fields of the item as putExtras() of the returnIntent?
Should the listActivity 'repaint' the entire data view or should it simply append the newly created data item dynamically? Will the answer to this question change if the listActivity also has to handle delete & edit events? What if the list view is NOT a 2-column grid but a single column list?

Should the createActivity store the new data item in the permanent storage and return only the ID of the newly created item to the listActivity OR should it return all the data fields of the item as putExtras() of the returnIntent?
That depends on what your listActivity needs to know about the new item. Generally saving the data in storage and only sending back the ID should be enough - based on my answer to some of your following questions. You might also need some indicator of the action that has been performed (Create, edit or delete).
Should the listActivity 'repaint' the entire data view or should it simply append the newly created data item dynamically?
Yes, if something in the underlying Adapters data set has changed a repaint is most probably needed (or at least calling notifyDataSetChanged() on the Adapter). If the order of the items in the list does not matter, you could just append the item to the list - but I still recommend that you save it in storage and then retrieve it when you want to add it to the Adapter. This is also why you would only need to pass the ID around. Also in order to append you would need some way of knowing if the last listitem has one or two columns filled.
Will the answer to this question change if the listActivity also has to handle delete & edit events?
The edit functionality is basicly the same as created (except the fields have values when you open the edit view). If you delete an item from the list a full repaint of the list is probably the best thing to do, as to not confuse the order of the items.
What if the list view is NOT a 2-column grid but a single column list?
Appending would be easier - but there is not much difference. In a single column list you might be able to avoid some full repaints that would be needed in a 2-column list - though I don't think it will make much difference.

Related

How can I efficiently transfer checked items from a listview to another activity when data is supplied by a Content Provider

The title doesn't really cover it all. It's basically the following use case:
Select a bunch of items in a listview
Move to the next activity
Show the selected items in this new activity in a listview
If the user decides to move to the previous section the same items should still be checked
If I were using POJOs I could simply add an OnItemClickListener to the ListView and add the items to an array each time user clicks an item and ship this array to the new Activity. However the ListView is populated using a Loader which gets the data from a ContentProvider and puts it in a SimpleCursorAdapter.
In the current state I can think of a few possible solutions:
1) Add an extra column to the relevant table of the objects in the ListView. Each time the user selects an item this column is updated to indicate it is selected.
This has a few advantages:
Once I have moved to the next Activity I can simply query for all selected items.
When moving to the previous activity I can use this column to show a selected view.
But also a few disadvantages:
Requires an update each time an item is clicked, triggering the loader.
Requires a custom adapter which uses the state of the new column to decide whether it should or should not be shown as checked. Possibly creating a delay between clicking an item and actually showing it as checked.
The default check options in the ListView will be unusable
2) Track the IDs of checked items (using OnItemClickedListener or getCheckedItemIds) and pass them to the next Activity. In the new activity I then create a selection argument of "ID = ? OR " repeating N times (and excluding the last OR) and use the given array as the selection arguments.
Advantages:
No need to keep updating the database.
No extra columns in the database.
Item checking has no extra delay.
Default check options from the listview still usable
Disadvantages:
Moving to the previous activity is now harder. I could return the list of selected item IDs, but the listview only has the option setItemChecked which takes a position. So I'd have to iterate over the entire adapter to find the positions of the items and set them as checked.
I'm probably capable of implementing them without any hassle. At the moment I'm gravitating towards the second option.
So ultimately I have the following questions:
Is there an easier way to do this in Android.
What would be a good way to recheck the items (see the disadvantage in the second suggestion and if there's no better way to do it).
This ListView will also get a search function which will probably again make it a bit harder because if I'm not mistaken filtering resets it every time. So I'd also have to recheck items every time (ideally during filtering).
Your disadvantage "Requires an update each time an item is clicked, triggering the loader." is not quite true it will trigger only if your ContentProvider calls notifyChange you could have it not to call notifyChange in some specific cases
and pressing back by going to the previous activity shouldn't be that hard only if you explicitly call finish() on your activity, otherwise it should be able to save its state onSaveInstanceState
Either way i would use a third approach and simply wouldn't use a second activity but would keep everything inside a single activity use pearhaps two Fragments one for the initial check list and the second one for your second preselected list and would use callbacks and let the activity manage all,is that possible for your use case ?

Complex Items in a Listview

I have a ListView where the view for each item is a string (the name of the item). But I have to associate a lot of other data with that item: price, size, weight, tax, etc. So, I'm of creating a new Java class called Item, and then an object for each item in the list.
I don't know which is the bext way to implement this. There's two obvious choices:
1) I can simply create the data structure outside of any Android Views, and then write a method called UpdateList() which takes the name of each item in this data structure and puts it in the ListView. The problem with this is that some of the data is duplicated twice (the original data structure, and the adapter for the ListView) and when you duplicate data, bug potential arises.
2) Or, I can somehow associate the data structure directly with the adapter for the ListView and have it figure out how to display the name for each ListView entry that is displayed. The advantage here is that you only have a single data structure. But I don't know if this is possible in Android, or very complex.
Which is the preferred way to do this with Android apps?
You would be better with the ListView and the Adapter option, You would need to create a custom ArrayAdapter to populate a ListView from this objects the way you want.
The advantage of this technic is that you gain a Views recycle mechanism that will recycle the Views inside you ListView in order to spend less memory.
In Short you would have to:
1. Create an object that represents your data for a single row.
2. Create an ArrayList of those objects.
3. Create a layout that contains a ListView or add a ListView to you main layout using code.
4. Create a layout of a single row.
5. Create a ViewHolder that will represent the visual aspect of you data row from the stand point of Views.
6. Create a custom ArrayAdapter that will populate the rows according to you needs.
7. Finally assign this ArrayAdapter to your ListView in onCreate.
You can get an Idea of how to implement this by reading this blog post I wrote:
Create a Custom ArrayAdapter
Just use the adapter. It's much cleaner. Then you can retrieve the info you need when you display the list item with getView(). See this example.

How to store and pass information between list views

The functionality of my app can be modeled after something like wanelo.
The user will enter a search term for what they want to buy in one Activity. They will get presented with a list of items that match that search term. So, the ListView will contain Items. An Item has many attributes, the main ones being:
id - corresponds to the Item's id in a database
date_modified - timestamp to know whether the Item was updated
remote_directory - a URL to the base directory of the Item's assets like icon and other images. The URL is formatted like this: http://my.domain.com/items/a1bc234d/ where a1bc234d is randomly generated, seeded by date_modified.
remote_dir_name - a substring of remote_directory. From the example above, this value would be a1bc234d.
From the list of search results, the user can mark an item to be viewed later. This will trigger a couple of things:
First, I want to ad the Item to a different ListView that represents the Items the user has "downloaded".
Then, I want to actually download of all of the Item's data: description, all assets in remote_directory. These things get stored my app's internal storage in folders remote_dir_name: /data/data/my.app.package.name/files/a1bc234d/.
These "downloaded" items are meant to be viewable in offline mode.
This "downloaded" ListView corresponds to a different Activity and will have list items that show a progress bar of the download status for an Item. Also, this ListView should be editable: use should be able to delete and re-order the Items in the list.
Finally, the "downloaded" ListView needs to be persistent. It should preserve order. The ListView of search results need not persist.
I'm having a lot of trouble figuring out how to store the list of Items getting downloaded. The "download" ListView needs to know when to update a list item's progress bar if it's getting downloaded. I think it's a little overkill to store the Items in a database because I'll be constantly updating a row's column until the download finishes. How should I pass this download status information between these two ListViews?
I am not entirely sure I am grasping the whole picture here, but it seems to me that you need two ArrayList fields.
List<Item> downloadedItems = new ArrayList<Item>;
List<Item> searchItems = new ArrayList<Item>;
then what you need to do is create your own custom ListAdapter for the DownloadListView and create your own custom download_item.xml that you will inflate inside of the ListAdapter. In your case it sounds like this download_item.xml will consist of a textview, and a progressbar, and will need the containing (or top layer) layout set to wrap content.
Now in the on click listener for the SearchListView set it so that it will call a function that will take the item that was tapped and add it to the downloadedItems ArrayList and start the download, as well as refresh the listadapter dataset so it knows to update the items in the list.
The download should be in a AsyncTask, and you will want to use the #Override publishProgress() portion of this, so that you can update the status of the download bar.
forgive me for any mis sights or mistakes, I just woke up.

one activity, multiple views?

I want to design a list with options to sort it in ascending or descending orders. I am able to do that using different intents. Is there a way to do that without having a new intent?
The example that comes to my mind is Manage Applications in android. Sort by name and size happen on the same screen. How is that done?
Edit - I have a list of say 20 items. Right now, I am sorting the list items and displaying only the top 5 items. I want to add an option to display the bottom 5 items too. I have done that by creating a new class exactle the same as prev class with top array replaced by bottom array.
You can re-sort the underlying data structure before setting it in the adapter.
Usually a list is displayed using a ListView.
ListViews usually have an adapter associated with them. The Views are listed in the order they exist in the adapter. So to change the order of elements in the list , all you have to do is set a new adapter to it where the the elements are ordered as you wish (You could also try to change of the order of elements of the existing adapter, but I don't know if it can be done).
You can see the ListView Hello World Example to have a better understanding of ListViews.
Umang, I don't have eclipse on hand now and I just want to express my train of thought to solve your problem. Please write the codes yourself and test it.
There must be an adapter associated with your listview, inside it, you can set a variable to moniter the order mode, like: private int mode;
Inside the getView() method of the adapter, based on the mode, return the items as you want.
I think you have finished the steps above, since you can change the order already.
In the first Activity, you can set some event for the user to chage the order, i.e, via the Menu. So you override public boolean onCreateOptionsMenu (Menu menu).
In the corresponding public boolean onOptionsItemSelected (MenuItem item), you set the mode value based on the item index the user selected.
Call adapter.notifyDataSetChanged() to notify the system that the data for the listView has been changed.
call listView.invalidate() to show the new ListView.
The ArrayAdapter class has a built-in method for sorting via "sort (Comparator comparator)", provided you are willing to go to the trouble to write the Comparators that you need to do the sorting. I use this method to sort "in place", without having to re-load the adapter with an externally re-ordered list.
Check out http://developer.android.com/reference/android/widget/ArrayAdapter.html
and http://developer.android.com/reference/java/util/Comparator.html

What's the best way to handle a list view whose cursor gets frequent reads and writes?

I am building an Inventory application. The items are shown in a grid view and each cell of the grid view also has a TextView in the upper right corner that displays the available quantity of the item. The user can single click on the gridview cell to increase the quantity or long click to decrease it.
I am currently using a class derived from SimpleCursorAdapter to display the data, but I am not sure about how to update the quantity in the DB. I am afraid that if I write directly to the DB and then create a new cursor and change cursor that the application might become bogged down if the user clicks repeatedly (say to add 10 items)
I have considered copying the data from the query cursor to an array in the Activity and then using an ArrayAdapter but this seems kludgy.
I have also thought about creating an array in my SimpleCursorAdapter which would cache items that have been modified and then save those items when pausing...
Is there a better way? A more Android way?
I guess this comes down to: what is the best way to make rapid changes in the DB and UI?
I don't know much about Cursors in this regard, but I would create a custom ArrayAdapter based on a model object rather than a Cursor. That's just a personal preference, but by doing this I don't have to make any assumptions about the Cursor implementation or know it inside and out.
Let's say you're displaying a collection of type Item in your grid. I would create a class called ItemsList that derives from ArrayList<Item> and my adapter would derive from ArrayAdapter<Item>. The reason you create a wrapper around the ArrayList is that you can allow the user to interact with it freely and mark it as "dirty" and allow it to update the database asynchronously. This way, you just call notifyDataSetChanged() on your adapter and you don't have to think about the overhead of updating the db...you've separated interacting with the collection being displayed and the process of updating the persistent storage.
Btw...this video is a must when working with ListViews and Adapters if you haven't already seen it:
http://www.youtube.com/watch?v=wDBM6wVEO70
You could use a regular listView and a regular Adapter with a list (arraylist) of items in it. Every time user clicks or long clicks you can edit the list in your adapter and notifyDataChanged() which will reflect the list changes on your listView. If you want to keep your list after user quits your application you can use either database(for bigger amount of data) or preferences (for smaller data amount).

Categories

Resources