ListView: Part 2.

Slides:



Advertisements
Similar presentations
ListView Examples. Basic Steps for Creating a Listview 1.Create a layout (e.g., a LinearLayout), with elements for –the ListView (
Advertisements

Android – CoNTENT PRoViders
 User Interface - Raeha Sandalwala.  Introduction to UI  Layouts  UI Controls  Menus and ‘Toasts’  Notifications  Other interesting UIs ◦ ListView.
@2011 Mihail L. Sichitiu1 Android Introduction Hello Views Part 1.
Cosc 4730 Android TabActivity and ListView. TabActivity A TabActivity allows for multiple “tabs”. – Each Tab is it’s own activity and the “root” activity.
Presenting Lists of Data. Lists of Data Issues involved – unknown number of elements – allowing the user to scroll Data sources – most common ArrayList.
SQLite Database. SQLite Public domain database – Advantages Small (about 150 KB) – Used on devices with limited resources Each database contained within.
Data Storage: Part 3 (SQLite)
Networking: Part 2 (Accessing the Internet). The UI Thread When an application is launched, the system creates a “main” UI thread responsible for handling.
Content providers Accessing shared data in a uniform way 1Content providers.
Data Storage: Part 4 (Content Providers). Content Providers Content providers allow the sharing of data between applications. Inter-process communication.
Package org.androidtown.database.query; import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase;
1 Announcements Homework #2 due Feb 7 at 1:30pm Submit the entire Eclipse project in Blackboard Please fill out the when2meets when your Project Manager.
Mobile Computing Lecture#11 Adapters and Dialogs.
ListView.
Create Navigation Drawer Team 2 Zhong Wang Jiaming Dong Philip Wu Lingduo Kong.
Address Book App 1. Define styles   Specify a background for a TextView – res/drawable/textview_border.xml.
9 Persistence - SQLite CSNB544 Mobile Application Development Thanks to Utexas Austin.
User Interfaces: Part 1 (View Groups and Layouts).
Cosc 5/4730 Android Communications Intents, callbacks, and setters.
1 Introducing Activity and Intent. 2 Memory LinearLayout, weight=2 LinearLayout, weight=1 TextView ListView.
Copyright© Jeffrey Jongko, Ateneo de Manila University Custom ListAdapters.
Applications with Multiple Activities. Most applications will have more than one activity. The main activity is started when the application is started.
ListView and ExpandableListView
Adapters 1 CS440. Adapters (again!)  Adapters are bridging classes, that bind data to user-interface Views. The adapter is responsible for creating the.
Address Book App 1 Fall 2014 CS7020: Game Design and Development.
David Sutton USING CONTENT PROVIDERS. TOPICS COVERED THIS WEEK  Persistence  Introduction to databases  Content providers  Cursors  Cursor adapters.
Mobile Programming Lecture 4 Resources, Selection, Activities, Intents.
Http :// developer. android. com / guide / topics / fundamentals. html.
By: Eliav Menachi.  On Android, all application data (including files) are private to that application  Android provides a standard way for an application.
School of Engineering and Information and Communication Technology KIT305/KIT607 Mobile Application Development Android OS –Permissions (cont.), Fragments,
Database Programming Code Dissection. Layered Approach Presentation (Activity) DbSampleActivity.java DataAccess (DataSource) CommentsDataSource.java MySQLiteHelper.java.
CMPE419 Mobile Application Development Asst.Prof.Dr.Ahmet Ünveren SPRING Computer Engineering Department Asst.Prof.Dr.Ahmet Ünveren
Making content providers
Data Storage: Part 3 (SQLite)
Lab7 – Appendix.
Permissions.
Content provider.
Android Content Providers & SQLite
Data Storage: Part 4 (Content Providers)
Content Providers And Content Resolvers
CS499 – Mobile Application Development
UNIT 11 로봇 전화번호부 3/4 로봇 SW 콘텐츠 교육원 조용수.
several communicating screens
CS240: Advanced Programming Concepts
GUI Programming Fundamentals
Further android gui programming
Android Application SQLite 1.
Concurrency in Android
CS499 – Mobile Application Development
CS499 – Mobile Application Development
ITEC535 – Mobile Programming
ANDROID UI – FRAGMENTS UNIT II.
CIS 470 Mobile App Development
Android Programming Lecture 6
CIS 470 Mobile App Development
Android Lists and Fragments
Android Topics Custom ArrayAdapters
Mobile Computing With Android ACST 4550 Android Database Storage
Activities and Intents
Android Developer Fundamentals V2
HNDIT2417 Mobile Application Development
Android Developer Fundamentals V2
CIS 470 Mobile App Development
ListView ? BaseAdapter ?.
ListView A view that shows items in a vertically scrolling list. The items come from the ListAdapter associated with this view. ListAdapter is used to.
SQLLite and Android.
plus content providers, loaders, recyclerview
CS 240 – Advanced Programming Concepts
CIS 694/EEC 693 Android Sensor Programming
Presentation transcript:

ListView: Part 2

Emergency Contacts The slides in this section and the following section on content providers present four versions of an emergency contacts application that uses an SQLite database. The functionality and screens for all examples are exactly the same. The differences lie in how each version is implemente. ©SoftMoore Consulting

Emergency Contacts ©SoftMoore Consulting

Versions of the Emergency Contacts Application Version 1: Uses an SQLite database and a modified ArrayAdapter. Version 2: Uses an SQLite database and a SimpleCursorAdapter. Version 3: Uses an SQLite database, a SimpleCursorAdapter, and a modified CursorLoader. Version 4: Uses a content provider, a CursorLoader, and a SimpleCursorAdapter. (Version 4 is postponed to section on content providers.) Versions 1 and 2 load the data into the ListView synchronously; i.e., the UI thread is blocked while the data is being loaded. (not suitable for large databases) Versions 3 and 4 use a CursorLoader to load the data asynchronously; i.e., the UI thread is not blocked while the data is being loaded. ©SoftMoore Consulting

Example: Emergency Contacts Version 1 Special considerations for this version: Implements an entity class for emergency contacts Uses extra helper methods in EmergencyDbOpenHelper Uses a custom array adapter to map values for name and phone number to the appropriate text views Using logic from previous slides for requesting permission to make a phone call ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Entity Class for Emergency Contacts) public class EmergencyContact implements Serializable { private static final long serialVersionUID = ...; private long id; private String name; private String phoneNum; public EmergencyContact() this(-1, null, null); } public EmergencyContact(String name, String phoneNum) this(-1, name, phoneNum); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Entity Class for Emergency Contacts – continued) public EmergencyContact(long id, String name, String phoneNum) { this.id = id; this.name = name; this.phoneNum = phoneNum; } public long getId() return id; public void setId(long id) (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Entity Class for Emergency Contacts – continued) ... // other get/set methods for name and phoneNum ... // override methods from class Object such as // toString(), hashCode(), and equals() } ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (EmergencyDbOpenHelper) public class EmergencyDbOpenHelper extends SQLiteOpenHelper { ... public List<EmergencyContact> getAllContacts() SQLiteDatabase db = this.getReadableDatabase(); List<EmergencyContact> contacts = new ArrayList<>(20); String query = "select * from " + EmergencyDbContract.TABLE_NAME; Cursor cursor = db.rawQuery(query, null); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (EmergencyDbOpenHelper – continued) while (cursor.moveToNext()) { int id = cursor.getInt(0); String name = cursor.getString(1); String phoneNum = cursor.getString(2); contacts.add(new EmergencyContact(id, name, phoneNum)); } cursor.close(); return contacts; (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (EmergencyDbOpenHelper – continued) public EmergencyContact insert(String name, String phoneNum) { // Note: no error checking SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(2); values.put(EmergencyDbContract.COLUMNS[1], name); values.put(EmergencyDbContract.COLUMNS[2], phoneNum); long id = db.insert(EmergencyDbContract.TABLE_NAME, null, values); EmergencyContact result = new EmergencyContact(id, name, phoneNum); db.close(); return result; } (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (EmergencyDbOpenHelper – continued) public void delete (EmergencyContact contact) { delete(contact.getId()); } public void delete (long id) // Note: no error checking SQLiteDatabase db = this.getWritableDatabase(); db.delete(EmergencyDbContract.TABLE_NAME, "_id = " + id, null); ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Layout for Each Item in the List) <LinearLayout ... android:orientation="vertical" android:padding="@dimen/contact_padding"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:textSize="@dimen/textSize_normal" /> android:id="@+id/phoneNum" android:textSize="@dimen/textSize_small" /> </LinearLayout> ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Custom Array Adapter for Emergency Contacts) /** * Custom array adapter to map emergency contacts to views. */ public class ContactAdapter extends ArrayAdapter<EmergencyContact> { public ContactAdapter(Context context, int layoutId, List<EmergencyContact> contacts) super(context, layoutId, contacts); } @Override public View getView(int position, View convertView, ViewGroup parent) // Get the data item for this position EmergencyContact contact = getItem(position); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Custom Array Adapter – continued) // Check if an existing view is being reused, // otherwise inflate the view if (convertView == null) { convertView = LayoutInflater.from(getContext()) .inflate(R.layout.contact_layout, parent, false); } // Look up views for data population TextView name = (TextView) convertView.findViewById(R.id.name); TextView phoneNum = (TextView) convertView.findViewById(R.id.phoneNum); name.setText(contact.getName()); phoneNum.setText(contact.getPhoneNum()); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Custom Array Adapter – continued) // Return the completed view to render on screen return convertView; } ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Main Activity) public class MainActivity extends AppCompatActivity { ... private EmergencyDbOpenHelper openHelper; private List<EmergencyContact> contacts = new ArrayList<>(20); private ContactAdapter adapter; private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) openHelper = new EmergencyDbOpenHelper(this); contacts = openHelper.getAllContacts(); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Main Activity – continued) adapter = new ContactAdapter(this, R.layout.contact_layout, contacts); lv.setAdapter(adapter); lv.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) EmergencyContact contact = (EmergencyContact) lv.getItemAtPosition(position); nameToCall = contact.getName(); phoneNumToCall = contact.getPhoneNum(); checkCallPhonePermission(); } }); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Main Activity – continued) lv.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener() { // in the onClick listener for dialog's positive button EmergencyContact contact = (EmergencyContact) lv.getItemAtPosition(position); openHelper.delete(contact); contacts.remove(position); adapter.notifyDataSetChanged(); }); // in the onClick listener for the add button Intent intent = new Intent(MainActivity.this, AddContactActivity.class); startActivityForResult(intent, ADD_CONTACT_ACTIVITY); } (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Main Activity – continued) @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == ADD_CONTACT_ACTIVITY && resultCode == RESULT_OK) EmergencyContact contact = (EmergencyContact) intent.getSerializableExtra("contact"); adapter.add(contact); adapter.notifyDataSetChanged(); } ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Second “Add Contact” Activity) // in the onClick listener for the submit button EmergencyContact contact = addContact(); if (contact != null) { Intent intent = new Intent(); intent.putExtra("contact", contact); setResult(RESULT_OK, intent); finish(); } else String message = getString(R.string.emptyNameOrPhone); Toast toast = Toast.makeText(AddContactActivity.this, message, Toast.LENGTH_SHORT); toast.show(); defined on next slide (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 1 (Second “Add Contact” Activity – continued) private EmergencyContact addContact() { EditText nameEditText = (EditText) findViewById(R.id.name); String name = nameEditText.getText().toString(); EditText phoneNumEditText = (EditText) findViewById(R.id.phoneNum); String phoneNum = phoneNumEditText.getText().toString(); if (name.length() > 0 && phoneNum.length() > 0) EmergencyDbOpenHelper openHelper = new EmergencyDbOpenHelper(this); EmergencyContact contact = openHelper.insert(name, phoneNum); openHelper.close(); return contact; } else return null; ©SoftMoore Consulting

Example: Emergency Contacts Version 2 Same layouts and screen shots as with Version 1 of Emergency Contacts Special considerations for this version: no entity class for emergency contacts fewer helper methods in EmergencyDbOpenHelper methods insert(String name, String phoneNum) and delete (long id) are retained other methods such as getAllContacts() are no longer required uses a SimpleCursorAdapter rather than an ArrayAdapter ©SoftMoore Consulting

Class SimpleCursorAdapter Class CursorAdapter maps columns from a cursor to TextViews or ImageViews defined in an XML file. Class SimpleCursorAdapter is a subclass of CursorAdapter that is relatively simple and easy to use. To use a SimpleCursorAdapter, specify the columns from the cursor, the views to display the columns (e.g., TextViews), and the XML files that defines the appearance of these views (i.e., the default layout and the row layout). Note: The Cursor must include a column named "_id" or this class will not work. ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Main Activity) ... private static final String[] COLUMNS = { "name", "phone_num" }; private static final int[] VIEWS = { R.id.name, R.id.phoneNum }; private EmergencyDbOpenHelper openHelper; private SimpleCursorAdapter adapter; private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { lv = (ListView) findViewById(R.id.contactListView); lv.setEmptyView(findViewById(R.id.empty_list)); openHelper = new EmergencyDbOpenHelper(this); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Main Activity – continued) lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) ViewGroup vg = (ViewGroup) view; TextView nameView = (TextView) vg.getChildAt(0); nameToCall = nameView.getText().toString(); TextView phoneNumView = (TextView) vg.getChildAt(1); phoneNumToCall = phoneNumView.getText().toString(); checkCallPhonePermission(); } }); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Main Activity – continued) lv.setOnItemLongClickListener( new AdapterView.OnItemLongClickListener() { ... // in the onClick listener for dialog's positive button openHelper.delete(id); resetAdapter(); }); Button addButton = (Button)findViewById(R.id.addButton); addButton.setOnClickListener(new View.OnClickListener() ... // start AddContactActivity for result (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Main Activity – continued) // Create an initially empty adapter adapter = new SimpleCursorAdapter(this, R.layout.contact_layout, null, COLUMNS, VIEWS, 0); lv.setAdapter(adapter); resetAdapter(); } these columns get mapped to these views ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Main Activity – continued) private void resetAdapter() { try // get a cursor for the emergency contacts table String query = "select * from " + EmergencyDbContract.TABLE_NAME; SQLiteDatabase db = openHelper.getReadableDatabase(); Cursor cursor = db.rawQuery(query, null); adapter.changeCursor(cursor); } catch (Exception ex) String errorMsg = "Error ... "; Log.e(LOG_TAG, errorMsg, ex); ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Main Activity – continued) @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == ADD_CONTACT_ACTIVITY && resultCode == RESULT_OK) resetAdapter(); } ©SoftMoore Consulting

Comments on Using a SimpleCursorAdapter Note that method getCursor() returns three columns (_id, name, and phone_num) Not every column returned by the cursor needs to be mapped to a view; e.g., _id is not mapped to a view in this example. ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Second “Add Contact” Activity) // in the onClick listener for the submit button EditText nameEditText = (EditText) findViewById(R.id.name); String name = nameEditText.getText().toString(); EditText phoneNumEditText = (EditText) findViewById(R.id.phoneNum); String phoneNum = phoneNumEditText.getText().toString(); if (name.length() > 0 && phoneNum.length() > 0) { EmergencyDbOpenHelper openHelper = new EmergencyDbOpenHelper(AddContactActivity.this); openHelper.insert(name, phoneNum); openHelper.close(); Intent intent = new Intent(); setResult(RESULT_OK, intent); finish(); } (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 2 (Second “Add Contact” Activity – continued) else { String message = getString(R.string.emptyNameOrPhone); Toast toast = Toast.makeText(AddContactActivity.this, message, Toast.LENGTH_SHORT); toast.show(); } ©SoftMoore Consulting

Example: Emergency Contacts Version 3 Same layouts and screen shots as with Version 1 of Emergency Contacts Special considerations for this version: no entity class for emergency contacts fewer helper methods in EmergencyDbOpenHelper methods insert(String name, String phoneNum) and delete (long id) are retained other methods such as getAllContacts() are no longer required uses a SimpleCursorAdapter rather than an ArrayAdapter uses a custom CursorLoader ©SoftMoore Consulting

CursorLoader The “recommended” way to query a database cursor is to use a CursorLoader and to implement interface LoaderManager.LoaderCallbacks<Cursor>. Advantages of using CursorLoader and LoaderManager Data is loaded asynchronously – does not block the UI thread. The loader monitors the source of the data and delivers new results when the content changes. The loader automatically reconnects to the last loader’s cursor when being recreated after a configuration change; i.e., it does not need to re-query the data. However, … class CursorLoader was designed for use with a content provider, and some workarounds are required when using a database without a content provider. ©SoftMoore Consulting

Example: Emergency Contacts Version 3 (AbstractCustomCursorLoader) public abstract class AbstractCustomCursorLoader extends CursorLoader { private final Loader.ForceLoadContentObserver mObserver = new Loader.ForceLoadContentObserver(); public AbstractCustomCursorLoader(Context context) super(context); } @Override public Cursor loadInBackground() Cursor cursor = getCursor(); (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 3 (AbstractCustomCursorLoader) if (cursor != null) { // Ensure the cursor window is filled cursor.getCount(); cursor.registerContentObserver(mObserver); } cursor.setNotificationUri(getContext().getContentResolver(), getContentUri()); return cursor; protected abstract Cursor getCursor(); protected abstract Uri getContentUri(); (continued on next slide) ©SoftMoore Consulting

Using AbstractCustomCursorLoader Two rules for using this class: Extend the abstract class and implement methods getCursor() and getContentUri(). Any time that the underlying database changes (e.g., after an insert or delete), make sure to call getContentResolver().notifyChange(myUri, null) where myUri is the same one returned from your implementation of method getContentUri(). ©SoftMoore Consulting

Example: Emergency Contacts Version 3 (EmergencyDbCursorLoader) public class EmergencyDbCursorLoader extends AbstractCustomCursorLoader { private EmergencyDbOpenHelper openHelper; public EmergencyDbCursorLoader(Context context) super(context); openHelper = new EmergencyDbOpenHelper(context); } (continued on next slide) ©SoftMoore Consulting

Example: Emergency Contacts Version 3 (EmergencyDbCursorLoader – continued) protected Cursor getCursor() { // get a cursor for the emergency contacts table String query = "select * from " + EmergencyDbContract.TABLE_NAME; SQLiteDatabase db = openHelper.getReadableDatabase(); Cursor cursor = db.rawQuery(query, null); return cursor; } protected Uri getContentUri() return EmergencyDbContract.CONTENT_URI; ©SoftMoore Consulting

Example: Emergency Contacts Version 3 Implementations for classes MainActivity and AddContactActivity are very similar to the Version 2 implementations. Summary of main differences for Version 3: Class MainActivity implements LoaderManager.LoaderCallbacks<Cursor> For the last line of onCreate() in the main activity Version 2 calls resetAdapter() Version 3 calls getLoaderManager().initLoader(0, null, this) When the data changes via database inserts or deletes Version 3 calls notifyDataSetChanged(). ©SoftMoore Consulting

Example: Emergency Contacts Version 3 (Main Activity) public void notifyDataSetChanged() { getContentResolver(). notifyChange(EmergencyDbContract.CONTENT_URI, null); } // the next three methods implement LoaderCallbacks<Cursor> @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) return new EmergencyDbCursorLoader(this); ©SoftMoore Consulting

Example: Emergency Contacts Version 3 (Main Activity – continued) @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // swap in the cursor adapter.swapCursor(data); } public void onLoaderReset(Loader<Cursor> loader) adapter.swapCursor(null); ©SoftMoore Consulting

Relevant Links List View Loaders https://developer.android.com/guide/topics/ui/layout/listview.html Loaders https://developer.android.com/guide/components/loaders.html Using Lists in Android with ListView – Tutorial http://www.vogella.com/tutorials/AndroidListView/article.html Using and ArrayAdapter with ListView https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView Making ListView Scrolling Smooth https://developer.android.com/training/improving-layouts/smooth-scrolling.html ©SoftMoore Consulting