The onCreate
method (Fig. 4.20) is called by the system:
• when the app loads
• if the app’s process was killed by the operating system while the app was in the background, and the app is then restored
• each time the configuration changes, such as when the user rotates the device or opens or closes a physical keyboard.
39 // called when MainActivity is first created
40 @Override
41 protected void onCreate(Bundle savedInstanceState)
42 {
43 super.onCreate(savedInstanceState);
44 setContentView(R.layout.activity_main);
45
46 // get references to the EditTexts
47 queryEditText = (EditText) findViewById(R.id.queryEditText);
48 tagEditText = (EditText) findViewById(R.id.tagEditText);
49
50 // get the SharedPreferences containing the user's saved searches
51 savedSearches = getSharedPreferences(SEARCHES, MODE_PRIVATE);
52
53 // store the saved tags in an ArrayList then sort them
54 tags = new ArrayList<String>(savedSearches.getAll().keySet());
55 Collections.sort(tags, String.CASE_INSENSITIVE_ORDER);
56
57 // create ArrayAdapter and use it to bind tags to the ListView
58 adapter = new ArrayAdapter<String>(this, R.layout.list_item, tags);
59 setListAdapter(adapter);
60
61 // register listener to save a new or edited search
62 ImageButton saveButton =
63 (ImageButton) findViewById(R.id.saveButton);
64 saveButton.setOnClickListener(saveButtonListener);
65
66 // register listener that searches Twitter when user touches a tag
67 getListView().setOnItemClickListener(itemClickListener);
68
69 // set listener that allows user to delete or edit a search
70 getListView().setOnItemLongClickListener(itemLongClickListener);
71 } // end method onCreate
72
The method initializes the Activity
’s instance variables and GUI components—we keep it simple so the app loads quickly. Line 43 makes the required call to the superclass’s onCreate
method. As in the previous app, the call to setContentView
(line 44) passes the constant R.layout.activity_main
to inflate the GUI from activity_main.xml
.
Lines 47–48 obtain references to the queryEditText
and tagEditText
to initialize the corresponding instance variables.
Line 51 uses the method getSharedPreferences (inherited from class Context
) to get a SharedPreferences
object that can read existing tag–query pairs (if any) from the SEARCHES
file. The first argument indicates the name of the file that contains the data. The second argument specifies the accessibility of the file and can be set to one of the following options:
• MODE_PRIVATE—The file is accessible only to this app. In most cases, you’ll use this option.
• MODE_WORLD_READABLE—Any app on the device can read from the file.
• MODE_WORLD_WRITABLE—Any app on the device can write to the file.
These constants can be combined with the bitwise OR operator (|
). We aren’t reading a lot of data in this app, so it’s fast enough to load the searches in onCreate
.
We’d like to display the search tags alphabetically so the user can easily find a search to perform. First, line 54 gets the String
s representing the keys in the SharedPreferences
object and stores them in tags
(an ArrayList<String>
). SharedPreferences
method getAll returns all the saved searches as a Map
(package java.util
)—a collection of key–value pairs. We then call method keySet on that object to get all the keys as a Set
(package java.util
)—a collection of unique values. The result is used to initialize tags
.
Line 55 uses Collections.sort to sort tags
. Since the user could enter tags using mixtures of uppercase and lowercase letters, we chose to perform a case-insensitive sort by passing the predefined Comparator<String>
object String.CASE_INSENSITIVE_ORDER as the second argument to Collections.sort
.
To display the results in a ListView
we create a new ArrayAdapter<String>
object (line 58) which maps the contents tags
to TextView
s that are displayed in MainActivity
’s ListView
. The ArrayAdapter<String>
’s constructor receives:
• the Context
(this
) in which the ListView
is displayed—this
is the MainActivity
• the resource ID (R.layout.list_item
) of the layout that’s used to display each item in the ListView
• a List<String>
containing the items to display—tags
is an ArrayList<String>
, which implements interface List<String>
, so tags
is a List<String>
.
Line 59 uses inherited ListActivity
method setListAdapter to bind the ListView
to the ArrayAdapter
, so that the ListView
can display the data.
Lines 62–63 obtain a reference to the saveButton
and line 64 registers its listener—instance variable saveButtonListener
refers to an anonymous-inner-class object that implements interface OnClickListener
(Fig. 4.21). Line 67 uses inherited ListActivity
method getListView to get a reference to this activity’s ListView
, then registers the ListView
’s OnItemClickListener
—instance variable itemClickListener
refers to an anonymous inner class object that implements this interface (Fig. 4.24). Similarly, line 70 registers the ListView
’s OnItemLongClickListener
—instance variable itemLongClickListener
refers to an anonymous-inner-class object that implements this interface (Fig. 4.25).
73 // saveButtonListener saves a tag-query pair into SharedPreferences
74 public OnClickListener saveButtonListener = new OnClickListener()
75 {
76 @Override
77 public void onClick(View v)
78 {
79 // create tag if neither queryEditText nor tagEditText is empty
80 if (queryEditText.getText().length() > 0 &&
81 tagEditText.getText().length() > 0)
82 {
83 addTaggedSearch(queryEditText.getText().toString(),
84 tagEditText.getText().toString());
85 queryEditText.setText(""); // clear queryEditText
86 tagEditText.setText(""); // clear tagEditText
87
88 ((InputMethodManager) getSystemService(
89 Context.INPUT_METHOD_SERVICE )).hideSoftInputFromWindow(
90 tagEditText.getWindowToken(), 0);
91 }
92 else // display message asking user to provide a query and a tag
93 {
94 // create a new AlertDialog Builder
95 AlertDialog.Builder builder =
96 new AlertDialog.Builder(MainActivity.this);
97
98 // set dialog's title and message to display
99 builder.setMessage(R.string.missingMessage);
100
101 // provide an OK button that simply dismisses the dialog
102 builder.setPositiveButton(R.string.OK, null );
103
104 // create AlertDialog from the AlertDialog.Builder
105 AlertDialog errorDialog = builder.create();
106 errorDialog.show(); // display the modal dialog
107 }
108 } // end method onClick
109 }; // end OnClickListener anonymous inner class
110