Java tutorial
/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ru.caseagency.twitteraddressbook.addressbook; import android.app.Activity; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract.Contacts; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import ru.caseagency.twitteraddressbook.R; /** * This fragment displays a list of contacts stored in the Contacts Provider. Each item in the list * shows the contact's thumbnail photo and display name. On devices with large screens, this * fragment's UI appears as part of a two-pane layout, along with the UI of * {@link ru.caseagency.twitteraddressbook.detailview.ContactDetailFragment}. On smaller screens, this fragment's UI appears as a single pane. * * This Fragment retrieves contacts based on a search string. If the user doesn't enter a search * string, then the list contains all the contacts in the Contacts Provider. If the user enters a * search string, then the list contains only those contacts whose data matches the string. The * Contacts Provider itself controls the matching algorithm, which is a "substring" search: if the * search string is a substring of any of the contacts data, then there is a match. * * On newer API platforms, the search is implemented in a SearchView in the ActionBar; as the user * types the search string, the list automatically refreshes to display results ("type to filter"). * On older platforms, the user must enter the full string and trigger the search. In response, the * trigger starts a new Activity which loads a fresh instance of this fragment. The resulting UI * displays the filtered list and disables the search feature to prevent furthering searching. */ public class ContactsListFragment extends ListFragment implements AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> { // Defines a tag for identifying log entries private static final String TAG = "ContactsListFragment"; private ContactsAdapter mAdapter; // The main query adapter // Contact selected listener that allows the activity holding this fragment to be notified of // a contact being selected private OnContactsInteractionListener mOnContactSelectedListener; /** * Fragments require an empty constructor. */ public ContactsListFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create the main contacts adapter mAdapter = new ContactsAdapter(getActivity()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the list fragment layout return inflater.inflate(R.layout.contact_list_fragment, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Set up ListView, assign adapter and set some listeners. The adapter was previously // created in onCreate(). setListAdapter(mAdapter); getListView().setOnItemClickListener(this); { // Initialize the loader, and create a loader identified by ContactsQuery.QUERY_ID getLoaderManager().initLoader(ContactsQuery.QUERY_ID, null, this); } } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { // Assign callback listener which the holding activity must implement. This is used // so that when a contact item is interacted with (selected by the user) the holding // activity will be notified and can take further action such as populating the contact // detail pane (if in multi-pane layout) or starting a new activity with the contact // details (single pane layout). mOnContactSelectedListener = (OnContactsInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnContactsInteractionListener"); } } @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // Gets the Cursor object currently bound to the ListView final Cursor cursor = mAdapter.getCursor(); // Moves to the Cursor row corresponding to the ListView item that was clicked cursor.moveToPosition(position); // Creates a contact lookup Uri from contact ID and lookup_key final Uri uri = Contacts.getLookupUri(cursor.getLong(ContactsQuery.ID), cursor.getString(ContactsQuery.LOOKUP_KEY)); // Notifies the parent activity that the user selected a contact. In a two-pane layout, the // parent activity loads a ContactDetailFragment that displays the details for the selected // contact. In a single-pane layout, the parent activity starts a new activity that // displays contact details in its own Fragment. mOnContactSelectedListener.onContactSelected(uri); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { // If this is the loader for finding contacts in the Contacts Provider // (the only one supported) if (id == ContactsQuery.QUERY_ID) { Uri contentUri; contentUri = ContactsQuery.CONTENT_URI; // Returns a new CursorLoader for querying the Contacts table. No arguments are used // for the selection clause. The search string is either encoded onto the content URI, // or no contacts search string is used. The other search criteria are constants. See // the ContactsQuery interface. return new CursorLoader(getActivity(), contentUri, ContactsQuery.PROJECTION, ContactsQuery.SELECTION, null, ContactsQuery.SORT_ORDER); } Log.e(TAG, "onCreateLoader - incorrect ID provided (" + id + ")"); return null; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { // This swaps the new cursor into the adapter. if (loader.getId() == ContactsQuery.QUERY_ID) { mAdapter.swapCursor(data); } } @Override public void onLoaderReset(Loader<Cursor> loader) { if (loader.getId() == ContactsQuery.QUERY_ID) { // When the loader is being reset, clear the cursor from the adapter. This allows the // cursor resources to be freed. mAdapter.swapCursor(null); } } }