Don't use findViewById (part 1 -- account setup)

Added two new functions:
- UiUtilities.getView()
  is a fail-fast version of findViewById().  Crashes when there's no view
- setVisibilitySafe()
  same as View.setVisibility, but doesn't crash even if a view doesn't exist

Let's try to avoid the use of findViewById(), and instead use getView(), *right
after* the layout is inflated, so that we'll always fail-fast if a layout
doesn't have a required view.  (Rather than getting a NPE only when the view
is really accessed, which can be in a code path which is rarely executed--e.g.
only when there's a protocol error.)

Let's only use findViewById() only when we're sure no all the variants of a
layout have the view in question and leave a comment to make it clear it's on
purpose.

(UiUtilities has been moved from com.android.email to
com.android.email.activity)

Change-Id: I36e0bab65a989f5d34cf636f13e1eaee084547af
This commit is contained in:
Makoto Onuki 2011-03-28 13:15:23 -07:00
parent de70ee5f78
commit 2fbb3db5d8
21 changed files with 296 additions and 148 deletions

View File

@ -4,9 +4,9 @@
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.
@ -14,13 +14,15 @@
limitations under the License.
-->
<!-- small -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:text="@string/account_setup_account_type_instructions"
>
<TextView
android:text="@string/account_setup_account_type_instructions"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textAppearance="?android:attr/textAppearanceMedium"

View File

@ -17,7 +17,6 @@
package com.android.email.activity;
import com.android.email.R;
import com.android.email.UiUtilities;
import com.android.email.data.ClosingMatrixCursor;
import com.android.email.data.ThrottlingCursorLoader;
import com.android.emailcommon.provider.EmailContent;

View File

@ -20,7 +20,6 @@ import com.android.email.Controller;
import com.android.email.Email;
import com.android.email.EmailAddressAdapter;
import com.android.email.EmailAddressValidator;
import com.android.email.UiUtilities;
import com.android.email.R;
import com.android.email.mail.internet.EmailHtmlUtil;
import com.android.emailcommon.Logging;

View File

@ -18,7 +18,6 @@ package com.android.email.activity;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.UiUtilities;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Mailbox;

View File

@ -20,7 +20,6 @@ import com.android.email.AttachmentInfo;
import com.android.email.Controller;
import com.android.email.ControllerResultUiThreadWrapper;
import com.android.email.Email;
import com.android.email.UiUtilities;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.Throttle;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (C) 2011 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.
@ -14,12 +14,18 @@
* limitations under the License.
*/
package com.android.email;
package com.android.email.activity;
import com.android.email.R;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
public class UiUtilities {
private UiUtilities() {
}
/**
* Formats the given size as a String in bytes, kB, MB or GB. Ex: 12,315,000 = 11 MB
@ -59,4 +65,48 @@ public class UiUtilities {
return Integer.toString(count);
}
}
/**
* Same as {@link Activity#findViewById}, but crashes if there's no view.
*/
public static View getView(Activity parent, int viewId) {
return checkView(parent.findViewById(viewId));
}
/**
* Same as {@link View#findViewById}, but crashes if there's no view.
*/
public static View getView(View parent, int viewId) {
return checkView(parent.findViewById(viewId));
}
private static View checkView(View v) {
if (v == null) {
throw new IllegalArgumentException("View doesn't exist");
}
return v;
}
/**
* Same as {@link View#setVisibility(int)}, but doesn't crash even if {@code view} is null.
*/
public static void setVisibilitySafe(View v, int visibility) {
if (v != null) {
v.setVisibility(visibility);
}
}
/**
* Same as {@link View#setVisibility(int)}, but doesn't crash even if {@code view} is null.
*/
public static void setVisibilitySafe(Activity parent, int viewId, int visibility) {
setVisibilitySafe(parent.findViewById(viewId), visibility);
}
/**
* Same as {@link View#setVisibility(int)}, but doesn't crash even if {@code view} is null.
*/
public static void setVisibilitySafe(View parent, int viewId, int visibility) {
setVisibilitySafe(parent.findViewById(viewId), visibility);
}
}

View File

@ -17,6 +17,7 @@
package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
@ -57,7 +58,7 @@ public abstract class AccountServerBaseFragment extends Fragment
/*package*/ HostAuth mLoadedRecvAuth;
// This is null in the setup wizard screens, and non-null in AccountSettings mode
public Button mProceedButton;
private Button mProceedButton;
// This is used to debounce multiple clicks on the proceed button (which does async work)
private boolean mProceedButtonPressed;
/*package*/ String mBaseScheme = "protocol";
@ -136,8 +137,8 @@ public abstract class AccountServerBaseFragment extends Fragment
*/
protected void onCreateViewSettingsMode(View view) {
if (mSettingsMode) {
view.findViewById(R.id.cancel).setOnClickListener(this);
mProceedButton = (Button) view.findViewById(R.id.done);
UiUtilities.getView(view, R.id.cancel).setOnClickListener(this);
mProceedButton = (Button) UiUtilities.getView(view, R.id.done);
mProceedButton.setOnClickListener(this);
mProceedButton.setEnabled(false);
}

View File

@ -20,6 +20,7 @@ import com.android.email.ExchangeUtils;
import com.android.email.R;
import com.android.email.VendorPolicyLoader;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.mail.Store;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
@ -33,9 +34,6 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Prompts the user to select an account type. The account type, along with the
* passed in email address, password and makeDefault are then passed on to the
@ -61,11 +59,11 @@ public class AccountSetupAccountType extends AccountSetupActivity implements OnC
// Otherwise proceed into this screen
setContentView(R.layout.account_setup_account_type);
((Button)findViewById(R.id.pop)).setOnClickListener(this);
((Button)findViewById(R.id.imap)).setOnClickListener(this);
final Button exchangeButton = (Button) findViewById(R.id.exchange);
UiUtilities.getView(this, R.id.pop).setOnClickListener(this);
UiUtilities.getView(this, R.id.imap).setOnClickListener(this);
final Button exchangeButton = (Button) UiUtilities.getView(this, R.id.exchange);
exchangeButton.setVisibility(View.INVISIBLE);
final Button previousButton = (Button) findViewById(R.id.previous);
final Button previousButton = (Button) findViewById(R.id.previous); // xlarge only
if (previousButton != null) previousButton.setOnClickListener(this);
// TODO If we decide to exclude the Exchange option in POP_IMAP mode, use the following line

View File

@ -20,6 +20,7 @@ import com.android.email.EmailAddressValidator;
import com.android.email.R;
import com.android.email.VendorPolicyLoader;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.activity.Welcome;
import com.android.email.activity.setup.AccountSettingsUtils.Provider;
import com.android.email.mail.Store;
@ -198,10 +199,10 @@ public class AccountSetupBasics extends AccountSetupActivity
setContentView(R.layout.account_setup_basics);
mWelcomeView = (TextView) findViewById(R.id.instructions);
mEmailView = (EditText) findViewById(R.id.account_email);
mPasswordView = (EditText) findViewById(R.id.account_password);
mDefaultView = (CheckBox) findViewById(R.id.account_default);
mWelcomeView = (TextView) UiUtilities.getView(this, R.id.instructions);
mEmailView = (EditText) UiUtilities.getView(this, R.id.account_email);
mPasswordView = (EditText) UiUtilities.getView(this, R.id.account_password);
mDefaultView = (CheckBox) UiUtilities.getView(this, R.id.account_default);
mEmailView.addTextChangedListener(this);
mPasswordView.addTextChangedListener(this);
@ -226,8 +227,8 @@ public class AccountSetupBasics extends AccountSetupActivity
}
// Configure buttons
mManualButton = (Button) findViewById(R.id.manual_setup);
mNextButton = (Button) findViewById(R.id.next);
mManualButton = (Button) UiUtilities.getView(this, R.id.manual_setup);
mNextButton = (Button) UiUtilities.getView(this, R.id.next);
mManualButton.setVisibility(manualButtonDisplayed ? View.VISIBLE : View.INVISIBLE);
mManualButton.setOnClickListener(this);
mNextButton.setOnClickListener(this);
@ -665,10 +666,10 @@ public class AccountSetupBasics extends AccountSetupActivity
@Override
protected void onPostExecute(Integer numAccounts) {
if (numAccounts > 0) {
Activity activity = AccountSetupBasics.this;
activity.findViewById(R.id.account_default_divider_1).setVisibility(View.VISIBLE);
mDefaultView.setVisibility(View.VISIBLE);
activity.findViewById(R.id.account_default_divider_2).setVisibility(View.VISIBLE);
Activity a = AccountSetupBasics.this;
UiUtilities.setVisibilitySafe(mDefaultView, View.VISIBLE);
UiUtilities.setVisibilitySafe(a, R.id.account_default_divider_1, View.VISIBLE);
UiUtilities.setVisibilitySafe(a, R.id.account_default_divider_2, View.VISIBLE);
}
}
}

View File

@ -18,6 +18,7 @@ package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.HostAuth;
@ -91,9 +92,9 @@ public class AccountSetupExchange extends AccountSetupActivity
getFragmentManager().findFragmentById(R.id.setup_fragment);
mFragment.setCallback(this);
mNextButton = (Button) findViewById(R.id.next);
mNextButton = (Button) UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(this);
findViewById(R.id.previous).setOnClickListener(this);
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
// One-shot to launch autodiscovery at the entry to this activity (but not if it restarts)
mStartedAutoDiscovery = false;

View File

@ -20,6 +20,7 @@ import com.android.email.AccountBackupRestore;
import com.android.email.Email;
import com.android.email.ExchangeUtils;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email.mail.Store;
import com.android.emailcommon.Device;
import com.android.emailcommon.Logging;
@ -65,7 +66,6 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
private EditText mServerView;
private CheckBox mSslSecurityView;
private CheckBox mTrustCertificatesView;
private View mTrustCertificatesDivider;
// Support for lifecycle
private boolean mStarted;
@ -103,13 +103,13 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
View view = inflater.inflate(layoutId, container, false);
Context context = getActivity();
mUsernameView = (EditText) view.findViewById(R.id.account_username);
mPasswordView = (EditText) view.findViewById(R.id.account_password);
mServerView = (EditText) view.findViewById(R.id.account_server);
mSslSecurityView = (CheckBox) view.findViewById(R.id.account_ssl);
mUsernameView = (EditText) UiUtilities.getView(view, R.id.account_username);
mPasswordView = (EditText) UiUtilities.getView(view, R.id.account_password);
mServerView = (EditText) UiUtilities.getView(view, R.id.account_server);
mSslSecurityView = (CheckBox) UiUtilities.getView(view, R.id.account_ssl);
mSslSecurityView.setOnCheckedChangeListener(this);
mTrustCertificatesView = (CheckBox) view.findViewById(R.id.account_trust_certificates);
mTrustCertificatesDivider = view.findViewById(R.id.account_trust_certificates_divider);
mTrustCertificatesView = (CheckBox) UiUtilities.getView(view,
R.id.account_trust_certificates);
// Calls validateFields() which enables or disables the Next button
// based on the fields' validity.
@ -124,13 +124,13 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
mUsernameView.addTextChangedListener(validationTextWatcher);
mPasswordView.addTextChangedListener(validationTextWatcher);
mServerView.addTextChangedListener(validationTextWatcher);
String deviceId = "";
try {
String deviceId = Device.getDeviceId(context);
((TextView) view.findViewById(R.id.device_id)).setText(deviceId);
deviceId = Device.getDeviceId(context);
} catch (IOException e) {
// Not required
}
((TextView) UiUtilities.getView(view, R.id.device_id)).setText(deviceId);
// Additional setup only used while in "settings" mode
onCreateViewSettingsMode(view);
@ -318,10 +318,7 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
public void showTrustCertificates(boolean visible) {
int mode = visible ? View.VISIBLE : View.GONE;
mTrustCertificatesView.setVisibility(mode);
// Divider is optional (only on XL layouts)
if (mTrustCertificatesDivider != null) {
mTrustCertificatesDivider.setVisibility(mode);
}
UiUtilities.setVisibilitySafe(getView(), R.id.account_trust_certificates_divider, mode);
}
/**

View File

@ -18,6 +18,7 @@ package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.provider.EmailContent.Account;
import android.app.Activity;
@ -59,9 +60,9 @@ public class AccountSetupIncoming extends AccountSetupActivity
// Configure fragment
mFragment.setCallback(this);
mNextButton = (Button) findViewById(R.id.next);
mNextButton = (Button) UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(this);
findViewById(R.id.previous).setOnClickListener(this);
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
}
/**

View File

@ -19,6 +19,7 @@ package com.android.email.activity.setup;
import com.android.email.AccountBackupRestore;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email.mail.Store;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent.Account;
@ -110,16 +111,17 @@ public class AccountSetupIncomingFragment extends AccountServerBaseFragment {
View view = inflater.inflate(layoutId, container, false);
Context context = getActivity();
mUsernameView = (EditText) view.findViewById(R.id.account_username);
mPasswordView = (EditText) view.findViewById(R.id.account_password);
mServerLabelView = (TextView) view.findViewById(R.id.account_server_label);
mServerView = (EditText) view.findViewById(R.id.account_server);
mPortView = (EditText) view.findViewById(R.id.account_port);
mSecurityTypeView = (Spinner) view.findViewById(R.id.account_security_type);
mDeletePolicyLabelView = (TextView) view.findViewById(R.id.account_delete_policy_label);
mDeletePolicyView = (Spinner) view.findViewById(R.id.account_delete_policy);
mImapPathPrefixSectionView = view.findViewById(R.id.imap_path_prefix_section);
mImapPathPrefixView = (EditText) view.findViewById(R.id.imap_path_prefix);
mUsernameView = (EditText) UiUtilities.getView(view, R.id.account_username);
mPasswordView = (EditText) UiUtilities.getView(view, R.id.account_password);
mServerLabelView = (TextView) UiUtilities.getView(view, R.id.account_server_label);
mServerView = (EditText) UiUtilities.getView(view, R.id.account_server);
mPortView = (EditText) UiUtilities.getView(view, R.id.account_port);
mSecurityTypeView = (Spinner) UiUtilities.getView(view, R.id.account_security_type);
mDeletePolicyLabelView = (TextView) UiUtilities.getView(view,
R.id.account_delete_policy_label);
mDeletePolicyView = (Spinner) UiUtilities.getView(view, R.id.account_delete_policy);
mImapPathPrefixSectionView = UiUtilities.getView(view, R.id.imap_path_prefix_section);
mImapPathPrefixView = (EditText) UiUtilities.getView(view, R.id.imap_path_prefix);
// Set up spinners
SpinnerOption securityTypes[] = {

View File

@ -19,6 +19,7 @@ package com.android.email.activity.setup;
import com.android.email.AccountBackupRestore;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.activity.Welcome;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
@ -47,6 +48,7 @@ public class AccountSetupNames extends AccountSetupActivity implements OnClickLi
private EditText mDescription;
private EditText mName;
private View mAccountNameLabel;
private Button mNextButton;
private boolean mNextPressed = false;
private boolean mEasAccount = false;
@ -60,9 +62,10 @@ public class AccountSetupNames extends AccountSetupActivity implements OnClickLi
super.onCreate(savedInstanceState);
ActivityHelper.debugSetWindowFlags(this);
setContentView(R.layout.account_setup_names);
mDescription = (EditText) findViewById(R.id.account_description);
mName = (EditText) findViewById(R.id.account_name);
mNextButton = (Button) findViewById(R.id.next);
mDescription = (EditText) UiUtilities.getView(this, R.id.account_description);
mName = (EditText) UiUtilities.getView(this, R.id.account_name);
mAccountNameLabel = UiUtilities.getView(this, R.id.account_name_label);
mNextButton = (Button) UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(this);
TextWatcher validationTextWatcher = new TextWatcher() {
@ -91,7 +94,7 @@ public class AccountSetupNames extends AccountSetupActivity implements OnClickLi
mEasAccount = "eas".equals(account.mHostAuthRecv.mProtocol);
if (mEasAccount) {
mName.setVisibility(View.GONE);
findViewById(R.id.account_name_label).setVisibility(View.GONE);
mAccountNameLabel.setVisibility(View.GONE);
}
/*
* Since this field is considered optional, we don't set this here. If

View File

@ -20,6 +20,7 @@ import com.android.email.Email;
import com.android.email.ExchangeUtils;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.email.mail.Store;
import com.android.email.service.MailService;
import com.android.emailcommon.Logging;
@ -63,6 +64,7 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
private CheckBox mSyncCalendarView;
private CheckBox mSyncEmailView;
private CheckBox mBackgroundAttachmentsView;
private View mAccountSyncWindowRow;
private boolean mDonePressed = false;
public static final int REQUEST_CODE_ACCEPT_POLICIES = 1;
@ -80,18 +82,20 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
ActivityHelper.debugSetWindowFlags(this);
setContentView(R.layout.account_setup_options);
mCheckFrequencyView = (Spinner)findViewById(R.id.account_check_frequency);
mSyncWindowView = (Spinner) findViewById(R.id.account_sync_window);
mDefaultView = (CheckBox)findViewById(R.id.account_default);
mNotifyView = (CheckBox)findViewById(R.id.account_notify);
mSyncContactsView = (CheckBox) findViewById(R.id.account_sync_contacts);
mSyncCalendarView = (CheckBox) findViewById(R.id.account_sync_calendar);
mSyncEmailView = (CheckBox) findViewById(R.id.account_sync_email);
mCheckFrequencyView = (Spinner) UiUtilities.getView(this, R.id.account_check_frequency);
mSyncWindowView = (Spinner) UiUtilities.getView(this, R.id.account_sync_window);
mDefaultView = (CheckBox) UiUtilities.getView(this, R.id.account_default);
mNotifyView = (CheckBox) UiUtilities.getView(this, R.id.account_notify);
mSyncContactsView = (CheckBox) UiUtilities.getView(this, R.id.account_sync_contacts);
mSyncCalendarView = (CheckBox) UiUtilities.getView(this, R.id.account_sync_calendar);
mSyncEmailView = (CheckBox) UiUtilities.getView(this, R.id.account_sync_email);
mSyncEmailView.setChecked(true);
mBackgroundAttachmentsView = (CheckBox) findViewById(R.id.account_background_attachments);
mBackgroundAttachmentsView = (CheckBox) UiUtilities.getView(this,
R.id.account_background_attachments);
mBackgroundAttachmentsView.setChecked(true);
findViewById(R.id.previous).setOnClickListener(this);
findViewById(R.id.next).setOnClickListener(this);
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
UiUtilities.getView(this, R.id.next).setOnClickListener(this);
mAccountSyncWindowRow = UiUtilities.getView(this, R.id.account_sync_window_row);
// Generate spinner entries using XML arrays used by the preferences
int frequencyValuesId;
@ -142,14 +146,15 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
mSyncCalendarView.setVisibility(View.VISIBLE);
mSyncCalendarView.setChecked(true);
// Show the associated dividers
findViewById(R.id.account_sync_contacts_divider).setVisibility(View.VISIBLE);
findViewById(R.id.account_sync_calendar_divider).setVisibility(View.VISIBLE);
UiUtilities.setVisibilitySafe(this, R.id.account_sync_contacts_divider, View.VISIBLE);
UiUtilities.setVisibilitySafe(this, R.id.account_sync_calendar_divider, View.VISIBLE);
}
// If we are in POP3, hide the "Background Attachments" mode
if ("pop3".equals(info.mScheme)) {
mBackgroundAttachmentsView.setVisibility(View.GONE);
findViewById(R.id.account_background_attachments_divider).setVisibility(View.GONE);
UiUtilities.setVisibilitySafe(this, R.id.account_background_attachments_divider,
View.GONE);
}
// If we are just visiting here to fill in details, exit immediately
@ -213,7 +218,7 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
account.setFlags(newFlags);
account.setSyncInterval((Integer)((SpinnerOption)mCheckFrequencyView
.getSelectedItem()).value);
if (findViewById(R.id.account_sync_window_row).getVisibility() == View.VISIBLE) {
if (mAccountSyncWindowRow.getVisibility() == View.VISIBLE) {
int window = (Integer)((SpinnerOption)mSyncWindowView.getSelectedItem()).value;
account.setSyncLookback(window);
}
@ -373,7 +378,7 @@ public class AccountSetupOptions extends AccountSetupActivity implements OnClick
*/
private void enableEASSyncWindowSpinner() {
// Show everything
findViewById(R.id.account_sync_window_row).setVisibility(View.VISIBLE);
mAccountSyncWindowRow.setVisibility(View.VISIBLE);
// Generate spinner entries using XML arrays used by the preferences
CharSequence[] windowValues = getResources().getTextArray(

View File

@ -18,6 +18,7 @@ package com.android.email.activity.setup;
import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.provider.EmailContent.Account;
import android.app.Activity;
@ -59,9 +60,9 @@ public class AccountSetupOutgoing extends Activity
// Configure fragment
mFragment.setCallback(this);
mNextButton = (Button) findViewById(R.id.next);
mNextButton = (Button) UiUtilities.getView(this, R.id.next);
mNextButton.setOnClickListener(this);
findViewById(R.id.previous).setOnClickListener(this);
UiUtilities.getView(this, R.id.previous).setOnClickListener(this);
}
/**

View File

@ -19,6 +19,7 @@ package com.android.email.activity.setup;
import com.android.email.AccountBackupRestore;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Account;
@ -65,8 +66,6 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
private EditText mServerView;
private EditText mPortView;
private CheckBox mRequireLoginView;
private View mRequireLoginSettingsView;
private View mRequireLoginSettingsView2;
private Spinner mSecurityTypeView;
// Support for lifecycle
@ -103,14 +102,12 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
View view = inflater.inflate(layoutId, container, false);
Context context = getActivity();
mUsernameView = (EditText) view.findViewById(R.id.account_username);
mPasswordView = (EditText) view.findViewById(R.id.account_password);
mServerView = (EditText) view.findViewById(R.id.account_server);
mPortView = (EditText) view.findViewById(R.id.account_port);
mRequireLoginView = (CheckBox) view.findViewById(R.id.account_require_login);
mRequireLoginSettingsView = view.findViewById(R.id.account_require_login_settings);
mRequireLoginSettingsView2 = view.findViewById(R.id.account_require_login_settings_2);
mSecurityTypeView = (Spinner) view.findViewById(R.id.account_security_type);
mUsernameView = (EditText) UiUtilities.getView(view, R.id.account_username);
mPasswordView = (EditText) UiUtilities.getView(view, R.id.account_password);
mServerView = (EditText) UiUtilities.getView(view, R.id.account_server);
mPortView = (EditText) UiUtilities.getView(view, R.id.account_port);
mRequireLoginView = (CheckBox) UiUtilities.getView(view, R.id.account_require_login);
mSecurityTypeView = (Spinner) UiUtilities.getView(view, R.id.account_security_type);
mRequireLoginView.setOnCheckedChangeListener(this);
// Note: Strings are shared with AccountSetupIncomingFragment
@ -321,10 +318,9 @@ public class AccountSetupOutgoingFragment extends AccountServerBaseFragment
*/
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mRequireLoginSettingsView.setVisibility(isChecked ? View.VISIBLE : View.GONE);
if (mRequireLoginSettingsView2 != null) {
mRequireLoginSettingsView2.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
final int visibility = isChecked ? View.VISIBLE : View.GONE;
UiUtilities.setVisibilitySafe(getView(), R.id.account_require_login_settings, visibility);
UiUtilities.setVisibilitySafe(getView(), R.id.account_require_login_settings_2, visibility);
validateFields();
}

View File

@ -20,6 +20,7 @@ import com.android.email.Email;
import com.android.email.ExchangeUtils;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.activity.UiUtilities;
import com.android.email.service.MailService;
import com.android.emailcommon.Logging;
@ -59,16 +60,16 @@ public class DebugFragment extends Fragment implements OnCheckedChangeListener,
Context context = getActivity();
mPreferences = Preferences.getPreferences(context);
mVersionView = (TextView) view.findViewById(R.id.version);
mVersionView = (TextView) UiUtilities.getView(view, R.id.version);
mVersionView.setText(String.format(context.getString(R.string.debug_version_fmt).toString(),
context.getString(R.string.build_number)));
mEnableDebugLoggingView = (CheckBox) view.findViewById(R.id.debug_logging);
mEnableDebugLoggingView = (CheckBox) UiUtilities.getView(view, R.id.debug_logging);
mEnableDebugLoggingView.setChecked(Email.DEBUG);
mEnableExchangeLoggingView = (CheckBox) view.findViewById(R.id.exchange_logging);
mEnableExchangeLoggingView = (CheckBox) UiUtilities.getView(view, R.id.exchange_logging);
mEnableExchangeFileLoggingView =
(CheckBox) view.findViewById(R.id.exchange_file_logging);
(CheckBox) UiUtilities.getView(view, R.id.exchange_file_logging);
// Note: To prevent recursion while presetting checkboxes, assign all listeners last
mEnableDebugLoggingView.setOnCheckedChangeListener(this);
@ -84,20 +85,20 @@ public class DebugFragment extends Fragment implements OnCheckedChangeListener,
mEnableExchangeFileLoggingView.setVisibility(View.GONE);
}
view.findViewById(R.id.clear_webview_cache).setOnClickListener(this);
UiUtilities.getView(view, R.id.clear_webview_cache).setOnClickListener(this);
mInhibitGraphicsAccelerationView = (CheckBox)
view.findViewById(R.id.debug_disable_graphics_acceleration);
UiUtilities.getView(view, R.id.debug_disable_graphics_acceleration);
mInhibitGraphicsAccelerationView.setChecked(Email.sDebugInhibitGraphicsAcceleration);
mInhibitGraphicsAccelerationView.setOnCheckedChangeListener(this);
mForceOneMinuteRefreshView = (CheckBox)
view.findViewById(R.id.debug_force_one_minute_refresh);
UiUtilities.getView(view, R.id.debug_force_one_minute_refresh);
mForceOneMinuteRefreshView.setChecked(mPreferences.getForceOneMinuteRefresh());
mForceOneMinuteRefreshView.setOnCheckedChangeListener(this);
mEnableStrictModeView = (CheckBox)
view.findViewById(R.id.debug_enable_strict_mode);
UiUtilities.getView(view, R.id.debug_enable_strict_mode);
mEnableStrictModeView.setChecked(mPreferences.getEnableStrictMode());
mEnableStrictModeView.setOnCheckedChangeListener(this);

View File

@ -19,8 +19,8 @@ package com.android.email.widget;
import com.android.email.Email;
import com.android.email.R;
import com.android.email.ResourceHelper;
import com.android.email.UiUtilities;
import com.android.email.activity.MessageCompose;
import com.android.email.activity.UiUtilities;
import com.android.email.activity.Welcome;
import com.android.email.provider.WidgetProvider.WidgetService;
import com.android.emailcommon.provider.EmailContent.Mailbox;

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2011 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 com.android.email.activity;
import com.android.email.R;
import android.app.Activity;
import android.content.Context;
import android.test.AndroidTestCase;
import android.view.View;
import java.util.Locale;
public class UiUtilitiesTests extends AndroidTestCase {
public void testFormatSize() {
if (!"en".equalsIgnoreCase(Locale.getDefault().getLanguage())) {
return; // Only works on the EN locale.
}
assertEquals("0B", UiUtilities.formatSize(getContext(), 0));
assertEquals("1B", UiUtilities.formatSize(getContext(), 1));
assertEquals("1023B", UiUtilities.formatSize(getContext(), 1023));
assertEquals("1KB", UiUtilities.formatSize(getContext(), 1024));
assertEquals("1023KB", UiUtilities.formatSize(getContext(), 1024 * 1024 - 1));
assertEquals("1MB", UiUtilities.formatSize(getContext(), 1024 * 1024));
assertEquals("1023MB", UiUtilities.formatSize(getContext(), 1024 * 1024 * 1024 - 1));
assertEquals("1GB", UiUtilities.formatSize(getContext(), 1024 * 1024 * 1024));
assertEquals("5GB", UiUtilities.formatSize(getContext(), 5L * 1024 * 1024 * 1024));
}
public void testGetMessageCountForUi() {
final Context c = getContext();
// Negavive valeus not really expected, but at least shouldn't crash.
assertEquals("-1", UiUtilities.getMessageCountForUi(c, -1, true));
assertEquals("-1", UiUtilities.getMessageCountForUi(c, -1, false));
assertEquals("", UiUtilities.getMessageCountForUi(c, 0, true));
assertEquals("0", UiUtilities.getMessageCountForUi(c, 0, false));
assertEquals("1", UiUtilities.getMessageCountForUi(c, 1, true));
assertEquals("1", UiUtilities.getMessageCountForUi(c, 1, false));
assertEquals("999", UiUtilities.getMessageCountForUi(c, 999, true));
assertEquals("999", UiUtilities.getMessageCountForUi(c, 999, false));
final String moreThan999 = c.getString(R.string.more_than_999);
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1000, true));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1000, false));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1001, true));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1001, false));
}
public void testGetView() {
// Test for getView(Activity, int)
DummyActivity a = new DummyActivity();
DummyView v = new DummyView(getContext());
a.mDummyViewId = 10;
a.mDummyView = v;
assertEquals(v, UiUtilities.getView(a, 10));
try {
assertEquals(v, UiUtilities.getView(a, 11));
fail();
} catch (IllegalArgumentException expected) {
}
// TODO Test for getView(View, int)?
// Unfortunately View.findViewById is final, so can't use the same approach.
// Also it's a huge pain to set up an actual, nested views in unit tests, so let's leave
// it for now.
}
public void testSetVisibilitySafe() {
{
DummyView v = new DummyView(getContext());
UiUtilities.setVisibilitySafe(v, View.VISIBLE);
assertEquals(View.VISIBLE, v.mVisibility);
// Shouldn't crash
UiUtilities.setVisibilitySafe(null, View.VISIBLE);
}
{
DummyActivity a = new DummyActivity();
DummyView v = new DummyView(getContext());
a.mDummyViewId = 3;
a.mDummyView = v;
UiUtilities.setVisibilitySafe(a, 3, View.VISIBLE);
assertEquals(View.VISIBLE, v.mVisibility);
// shouldn't crash
UiUtilities.setVisibilitySafe(a, 5, View.VISIBLE);
}
// No test for setVisibilitySafe(View, int, int) -- see testGetView().
}
private static class DummyActivity extends Activity {
public int mDummyViewId;
public View mDummyView;
@Override
public View findViewById(int id) {
return (id == mDummyViewId) ? mDummyView : null;
}
}
private static class DummyView extends View {
public int mVisibility = View.GONE;
public DummyView(Context context) {
super(context);
}
@Override
public void setVisibility(int visibility) {
mVisibility = visibility;
}
}
}

View File

@ -20,7 +20,6 @@ import com.android.email.DBTestHelper;
import com.android.email.FolderProperties;
import com.android.email.R;
import com.android.email.TestUtils;
import com.android.email.UiUtilities;
import com.android.email.provider.ProviderTestUtils;
import com.android.emailcommon.provider.EmailContent.Account;
import com.android.emailcommon.provider.EmailContent.Attachment;
@ -53,11 +52,8 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import libcore.util.EmptyArray;
/**
* This is a series of unit tests for the Utility class. These tests must be locally
* complete - no server(s) required.
@ -231,21 +227,6 @@ public class UtilityUnitTests extends AndroidTestCase {
Utility.cleanUpMimeDate("Thu, 10 Dec 09 15:08:08 -0700"));
}
public void testFormatSize() {
if (!"en".equalsIgnoreCase(Locale.getDefault().getLanguage())) {
return; // Only works on the EN locale.
}
assertEquals("0B", UiUtilities.formatSize(getContext(), 0));
assertEquals("1B", UiUtilities.formatSize(getContext(), 1));
assertEquals("1023B", UiUtilities.formatSize(getContext(), 1023));
assertEquals("1KB", UiUtilities.formatSize(getContext(), 1024));
assertEquals("1023KB", UiUtilities.formatSize(getContext(), 1024 * 1024 - 1));
assertEquals("1MB", UiUtilities.formatSize(getContext(), 1024 * 1024));
assertEquals("1023MB", UiUtilities.formatSize(getContext(), 1024 * 1024 * 1024 - 1));
assertEquals("1GB", UiUtilities.formatSize(getContext(), 1024 * 1024 * 1024));
assertEquals("5GB", UiUtilities.formatSize(getContext(), 5L * 1024 * 1024 * 1024));
}
private static class MyNewFileCreator implements NewFileCreator {
private final HashSet<String> mExistingFileNames;
@ -463,31 +444,6 @@ public class UtilityUnitTests extends AndroidTestCase {
// TODO check style -- but how?
}
public void testGetMessageCountForUi() {
final Context c = getContext();
// Negavive valeus not really expected, but at least shouldn't crash.
assertEquals("-1", UiUtilities.getMessageCountForUi(c, -1, true));
assertEquals("-1", UiUtilities.getMessageCountForUi(c, -1, false));
assertEquals("", UiUtilities.getMessageCountForUi(c, 0, true));
assertEquals("0", UiUtilities.getMessageCountForUi(c, 0, false));
assertEquals("1", UiUtilities.getMessageCountForUi(c, 1, true));
assertEquals("1", UiUtilities.getMessageCountForUi(c, 1, false));
assertEquals("999", UiUtilities.getMessageCountForUi(c, 999, true));
assertEquals("999", UiUtilities.getMessageCountForUi(c, 999, false));
final String moreThan999 = c.getString(R.string.more_than_999);
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1000, true));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1000, false));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1001, true));
assertEquals(moreThan999, UiUtilities.getMessageCountForUi(c, 1001, false));
}
public void testAreStringsEqual() {
String s1;
String s2;