Android ApiDemos example resolution (35): App-& gt; Preferences-& gt; Adv

Source: Internet
Author: User

In the previous article, Android ApiDemo sample resolution (31): App-> Preferences-> Launching preferences uses the AdvancedPreferences defined in Advanced preferences.

This article describes AdvancedPreferences in detail. This example is called Advanced because it involves custom Preference and refreshes the value of a Preference in a work thread.

Preference is the base class that is displayed in PreferenceActivity (usually in the list) in a Preference. It is similar to a View displayed in the Activity. Preference actually accesses one item in Shared Preferences, and the key defined by Preference is the key value used to access Shared Preferences.

Like View, you can customize View. In Android, you can also customize Preference to display the program preferences for managing custom applications. In this example, MyPreference is used to customize a Preference to store the number of times a user clicks the Preference. The type is an integer and the initial value is 100. Its definitions in advanced_preferences.xml are as follows:

<Com. example. android. apis. app. MyPreference
Android: key = "my_preference"
Android: title = "@ string/title_my_preference"
Android: summary = "@ string/summary_my_preference"
Android: defaultValue = "100"/>

Preference defines many attributes, such as Default Value, dependency, enabled, icon, key, and so on. The Listener includes PreferenceChangeListener and PreferenceClickListener, which allows applications to respond to Preference value change events or users to click Preference events.

The following describes how to customize a Preference in the order of MyPreference code.

1. derived from the Preference base class.

[Java]
Public class MyPreference extends Preference
Public class MyPreference extends Preference

2. Similar to custom View, you can customize Layout for custom Preference. MyPreference uses R. layout. preference_widget_mypreference. The definition is simple and there is only one TextView, and its id is mypreference_widget. Generally, setWidgetLayoutResource is used in the constructor to set the Layout resource for the Preference derived class.

[Java] view plaincopyprint?
// This is the constructor called by the inflater
Public MyPreference (Context context, AttributeSet attrs ){
Super (context, attrs );

SetWidgetLayoutResource (R. layout. preference_widget_mypreference );
}
// This is the constructor called by the inflater
Public MyPreference (Context context, AttributeSet attrs ){
Super (context, attrs );
 
SetWidgetLayoutResource (R. layout. preference_widget_mypreference );
}

3. If you need to set attributes for the View in the custom Layout, you can do so in onBindView (View view. The following code sets the value of TextView to mClickCounter.

[Java]
@ Override
Protected void onBindView (View view ){
Super. onBindView (view );

// Set our custom views inside the layout
Final TextView myTextView
= (TextView) view. findViewById (R. id. mypreference_widget );
If (myTextView! = Null ){
MyTextView. setText (String. valueOf (mClickCounter ));
}
}
@ Override
Protected void onBindView (View view ){
Super. onBindView (view );
 
// Set our custom views inside the layout
Final TextView myTextView
= (TextView) view. findViewById (R. id. mypreference_widget );
If (myTextView! = Null ){
MyTextView. setText (String. valueOf (mClickCounter ));
}
}

 

4. If the custom Preference defines an initial value in XML, for example, the initial value of MyPreference android: defaultValue = "100", we want to use this initial value in the code to initialize the variable mClickCounter. The mClickCounter type is an integer. This variable is used to save the number of user buttons.

[Java]
@ Override
Protected Object ongetdefadefavalue (TypedArray a, int index ){
// This preference type's value type is Integer, so we read the default
// Value from the attributes as an Integer.
Return a. getInteger (index, 0 );
}

@ Override
Protected void onSetInitialValue (boolean restoreValue, Object defaultValue ){
If (restoreValue ){
// Restore state
MClickCounter = getPersistedInt (mClickCounter );
} Else {
// Set state
Int value = (Integer) defaultValue;
MClickCounter = value;
PersistInt (value );
}
}
@ Override
Protected Object ongetdefadefavalue (TypedArray a, int index ){
// This preference type's value type is Integer, so we read the default
// Value from the attributes as an Integer.
Return a. getInteger (index, 0 );
}
 
@ Override
Protected void onSetInitialValue (boolean restoreValue, Object defaultValue ){
If (restoreValue ){
// Restore state
MClickCounter = getPersistedInt (mClickCounter );
} Else {
// Set state
Int value = (Integer) defaultValue;
MClickCounter = value;
PersistInt (value );
}
}

5. The onSaveInstanceState and onRestoreInstanceState methods are used to temporarily save or restore some variable values. Before Preference calls persistInt, persistBoolean, and persistString, the value of preference is not saved or updated in Shared preferences. If the user rotates the screen, the Activity is re-created, we need to retain the items selected during screen rotation. We can use onSaveInstanceState and onRestoreInstanceState to keep some temporary data.

[Java]
@ Override
Protected Parcelable onSaveInstanceState (){
/*
* Suppose a client uses this preference type without persisting. We
* Must save the instance state so it is able to, for example, keep ve
* Orientation changes.
*/

Final Parcelable superState = super. onSaveInstanceState ();
If (isPersistent ()){
// No need to save instance state since it's persistent
Return superState;
}

// Save the instance state
Final SavedState myState = new SavedState (superState );
MyState. clickCounter = mClickCounter;
Return myState;
}

@ Override
Protected void onRestoreInstanceState (Parcelable state ){
If (! State. getClass (). equals (SavedState. class )){
// Didn't save state for us in onSaveInstanceState
Super. onRestoreInstanceState (state );
Return;
}

// Restore the instance state
SavedState myState = (SavedState) state;
Super. onRestoreInstanceState (myState. getSuperState ());
MClickCounter = myState. clickCounter;
NotifyChanged ();
}
@ Override
Protected Parcelable onSaveInstanceState (){
/*
* Suppose a client uses this preference type without persisting. We
* Must save the instance state so it is able to, for example, keep ve
* Orientation changes.
*/
 
Final Parcelable superState = super. onSaveInstanceState ();
If (isPersistent ()){
// No need to save instance state since it's persistent
Return superState;
}
 
// Save the instance state
Final SavedState myState = new SavedState (superState );
MyState. clickCounter = mClickCounter;
Return myState;
}
 
@ Override
Protected void onRestoreInstanceState (Parcelable state ){
If (! State. getClass (). equals (SavedState. class )){
// Didn't save state for us in onSaveInstanceState
Super. onRestoreInstanceState (state );
Return;
}
 
// Restore the instance state
SavedState myState = (SavedState) state;
Super. onRestoreInstanceState (myState. getSuperState ());
MClickCounter = myState. clickCounter;
NotifyChanged ();
}

 

Here, SavedState is a subclass of BaseSavedState, which is not described in detail. BaseSavedState implements the Parcelable interface. The Serialable function on Windows is similar to the serialization function on other platforms.

6. MyPreference responds to the Click Event and saves the number of buttons to Shared Preferences.

[Java]
@ Override
Protected void onClick (){
Int newValue = mClickCounter + 1;
// Give the client a chance to ignore this change if they deem it
// Invalid
If (! CallChangeListener (newValue )){
// They don't want the value to be set
Return;
}

// Increment counter
MClickCounter = newValue;

// Save to persistent storage (this method will make sure this
// Preference shoshould be persistent, along with other useful checks)
PersistInt (mClickCounter );

// Data has changed, too y so UI can be refreshed!
NotifyChanged ();
}
@ Override
Protected void onClick (){
Int newValue = mClickCounter + 1;
// Give the client a chance to ignore this change if they deem it
// Invalid
If (! CallChangeListener (newValue )){
// They don't want the value to be set
Return;
}
 
// Increment counter
MClickCounter = newValue;
 
// Save to persistent storage (this method will make sure this
// Preference shoshould be persistent, along with other useful checks)
PersistInt (mClickCounter );
 
// Data has changed, too y so UI can be refreshed!
NotifyChanged ();
}

 

Preference uses persistBoolean, persistFloat, persistInt, persistLong, and persisitString to store data to Shared Preferences. Because mClickCounter is an integer, persistInt is used. NotifyChanged is used to notify the UI of data changes. CallChangeListener will call the registered Preference. OnPreferenceChangeListener to notify the Preference of changes.

Let's take a look at AdvancedPreferences. The code is not very long, as follows:

[Java]
Public class AdvancedPreferences
Extends PreferenceActivity
Implements OnSharedPreferenceChangeListener {
Public static final String KEY_MY_PREFERENCE
= "My_preference ";
Public static final String KEY_ADVANCED_CHECKBOX_PREFERENCE
= "Advanced_checkbox_preference ";

Private CheckBoxPreference mCheckBoxPreference;
Private Handler mHandler = new Handler ();

/**
* This is a simple example of controlling a preference from code.
*/
Private Runnable mForceCheckBoxRunnable = new Runnable (){
Public void run (){
If (mCheckBoxPreference! = Null ){
MCheckBoxPreference
. SetChecked (! MCheckBoxPreference. isChecked ());
}

// Force toggle again in a second
MHandler. postDelayed (this, 1000 );
}
};

@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );

// Load the XML preferences file
AddPreferencesFromResource (R. xml. advanced_preferences );

// Get a reference to the checkbox preference
MCheckBoxPreference
= (CheckBoxPreference) getPreferenceScreen ()
. FindPreference (KEY_ADVANCED_CHECKBOX_PREFERENCE );
}

@ Override
Protected void onResume (){
Super. onResume ();

// Start the force toggle
MForceCheckBoxRunnable. run ();

// Set up a listener whenever a key changes
GetPreferenceScreen ()
. GetSharedPreferences ()
. RegisterOnSharedPreferenceChangeListener (this );
}

@ Override
Protected void onPause (){
Super. onPause ();

// Unregister the listener whenever a key changes
GetPreferenceScreen ()
. GetSharedPreferences ()
. UnregisterOnSharedPreferenceChangeListener (this );

MHandler. removeCallbacks (mForceCheckBoxRunnable );
}

Public void onSharedPreferenceChanged (
SharedPreferences sharedPreferences,
String key ){
// Let's do something when my counter preference value changes
If (key. equals (KEY_MY_PREFERENCE )){
Toast. makeText (this, "Thanks! You increased my count"
+ SharedPreferences. getInt (key, 0 ),
Toast. LENGTH_SHORT). show ();
}
}

}
Public class AdvancedPreferences
Extends PreferenceActivity
Implements OnSharedPreferenceChangeListener {
Public static final String KEY_MY_PREFERENCE
= "My_preference ";
Public static final String KEY_ADVANCED_CHECKBOX_PREFERENCE
= "Advanced_checkbox_preference ";
 
Private CheckBoxPreference mCheckBoxPreference;
Private Handler mHandler = new Handler ();
 
/**
* This is a simple example of controlling a preference from code.
*/
Private Runnable mForceCheckBoxRunnable = new Runnable (){
Public void run (){
If (mCheckBoxPreference! = Null ){
MCheckBoxPreference
. SetChecked (! MCheckBoxPreference. isChecked ());
}
 
// Force toggle again in a second
MHandler. postDelayed (this, 1000 );
}
};
 
@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
 
// Load the XML preferences file
AddPreferencesFromResource (R. xml. advanced_preferences );
 
// Get a reference to the checkbox preference
MCheckBoxPreference
= (CheckBoxPreference) getPreferenceScreen ()
. FindPreference (KEY_ADVANCED_CHECKBOX_PREFERENCE );
}
 
@ Override
Protected void onResume (){
Super. onResume ();
 
// Start the force toggle
MForceCheckBoxRunnable. run ();
 
// Set up a listener whenever a key changes
GetPreferenceScreen ()
. GetSharedPreferences ()
. RegisterOnSharedPreferenceChangeListener (this );
}
 
@ Override
Protected void onPause (){
Super. onPause ();
 
// Unregister the listener whenever a key changes
GetPreferenceScreen ()
. GetSharedPreferences ()
. UnregisterOnSharedPreferenceChangeListener (this );
 
MHandler. removeCallbacks (mForceCheckBoxRunnable );
}
 
Public void onSharedPreferenceChanged (
SharedPreferences sharedPreferences,
String key ){
// Let's do something when my counter preference value changes
If (key. equals (KEY_MY_PREFERENCE )){
Toast. makeText (this, "Thanks! You increased my count"
+ SharedPreferences. getInt (key, 0 ),
Toast. LENGTH_SHORT). show ();
}
}
 
}

 

It implements OnSharedPreferenceChangeListener, so it can be used to listen to changes in MyPreference.

Handler, because the program needs to update the Preference value from the working thread, while the Preference is the UI, the UI cannot be directly updated from the working thread, and the Handler allows the working thread to update the UI, we will provide a detailed introduction later. In this example, the Haunted preference value is changed once every one second (select-> do not select ..)

RegisterOnSharedPreferenceChangeListener and unregisterOnSharedPreferenceChangeListener are used to register a general Preference change event processing code for SharedPreferences. In this example, the number of times the current button is displayed on the screen when MyPreference changes:

 
Author: mapdigit
 
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.