2016年12月27日 星期二


In Android, ListView / GridView / Spinner are commonly used for listing items and making selection. RecyclerView has similar function but its structure is a bit different, so not included here. They can be simple and easy to code when you understand their operations, otherwise they are troublesome.

Let’s start the talk:



INTRODUCTION J

They are all << AdapterView >>!!!

ListView / GridView / Spinner are subclasses of AdapterView. From the name, it is clear that it is a view with adapter. For this type of View, there are 3 building elements:

1.      Dataset: Your data should be something that can be put in a table. Every data item has same number of data fields.

Temporary states should also be considered. One common mistake: when item can be selected with no immediate action [e.g. allow selecting multiple items for Delete], data field - checked/selected is not added.

2.      Adapter: This is the linkage from dataset to user interface. It matches up data fields to corresponding display elements and takes care which item should be displayed. The appropriate adapter is mainly relied on the nature of the dataset but sometime also need to consider about UI actions. There are several different types of adapter. Some basic adapters are:

ArrayAdapter - TextView is referenced, it will be filled with the toString() of each object in the array. You can add lists or arrays of custom objects. Override the toString() method of your objects to determine what text will be displayed for the item in the list. To use something other than TextViews for the array display, for instance, ImageViews, or to have some of data besides toString() results fill the views, override getView(int, View, ViewGroup) to return the type of view you want.

BaseAdapter - Common base class of common implementation for an Adapter that can be used in both ListView (by implementing the specialized ListAdapter interface) and Spinner (by implementing the specialized SpinnerAdapter interface).

CursorAdapter - The Cursor must include a column named "_id" or this class will not work. Additionally, using MergeCursor with this class will not work if the merged Cursors have overlapping values in their "_id" columns.

SimpleAdapter - An easy adapter to map static data to views defined in an XML file. You can specify the data backing the list as an ArrayList of Maps. Each entry in the ArrayList corresponds to one row in the list. The Maps contain the data for each row. You also specify an XML file that defines the views used to display the row, and a mapping from keys in the Map to specific views. Binding data to views occurs in two phases. First, if a SimpleAdapter.ViewBinder is available, setViewValue(android.view.View, Object, String) is invoked. If the returned value is true, binding has occurred. If the returned value is false, the following views are then tried in order:

·     A view that implements Checkable (e.g. CheckBox). The expected bind value is a boolean.

·     TextView. The expected bind value is a string and setViewText(TextView, String) is invoked.

·     ImageView. The expected bind value is a resource id or a string and setViewImage(ImageView, int) or setViewImage(ImageView, String) is invoked.

SimpleCursorAdapter - An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file. You can specify which columns you want, which views you want to display the columns, and the XML file that defines the appearance of these views. Binding occurs in two phases. First, if a SimpleCursorAdapter.ViewBinder is available, setViewValue(android.view.View, android.database.Cursor, int) is invoked. If the returned value is true, binding has occured. If the returned value is false and the view to bind is a TextView, setViewText(TextView, String) is invoked. If the returned value is false and the view to bind is an ImageView, setViewImage(ImageView, String) is invoked. If this adapter is used with filtering, for instance in an AutoCompleteTextView, you can use the SimpleCursorAdapter.CursorToStringConverter and the FilterQueryProvider interfaces to get control over the filtering process.

3.      View: This is the User Interface/Layout XML files, presenting the data on the screen. 2 layout XML files is related. The first one contains the AdapterView. The second one defines the layout of single item/row [Android has some standard built-in layouts on this]. In Java code, we always refer the whole ListView / GridView / Spinner as parent/container/adapterView and item view as rowView/convertView/childView.





The above diagram is always drawn without the red solid arrows. However I would like to emphasis this because of one common mistake: when item view contains temporary states [e.g. CheckBox, Switch, ToggleButton, EditText/TextView as shopping cart counter etc.], view is changed/updated but forgot dataset. Therefore personally recommend the workflow like this:


UPDATE DATASET FIRST, THEN CALL ADAPTER [notifyDataSetChanged(), this method will be explained in more detail later] TO REDRAW VIEW. If that caused performance issue, then just replace notifyDataSetChanged() with code that update views directly. This makes sure that dataset is updated.

沒有留言:

張貼留言