improve performance of adapter implementations by caching index, use data uri where possible in ViewKeyActivity

This commit is contained in:
Dominik Schürmann 2014-01-19 00:00:56 +01:00
parent 12c7e219c8
commit 1bac2849b8
11 changed files with 226 additions and 66 deletions

View File

@ -3,7 +3,7 @@
<item
android:id="@+id/menu_key_list_public_multi_delete"
android:icon="@android:drawable/ic_menu_delete"
android:icon="@drawable/ic_action_discard"
android:title="@string/menu_delete_key"/>
</menu>

View File

@ -183,10 +183,10 @@
<string name="enter_passphrase_twice">Enter the passphrase twice.</string>
<string name="select_encryption_key">Select at least one encryption key.</string>
<string name="select_encryption_or_signature_key">Select at least one encryption key or a signature key.</string>
<string name="specify_file_to_encrypt_to">Please specify which file to encrypt to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specify_file_to_decrypt_to">Please specify which file to decrypt to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specify_file_to_export_to">Please specify which file to export to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specify_file_to_export_secret_keys_to">Please specify which file to export to.\nWARNING! You are about to export SECRET keys.\nWARNING! File will be overwritten if it exists.</string>
<string name="specify_file_to_encrypt_to">Please specify which file to encrypt to.\nWARNING: File will be overwritten if it exists.</string>
<string name="specify_file_to_decrypt_to">Please specify which file to decrypt to.\nWARNING: File will be overwritten if it exists.</string>
<string name="specify_file_to_export_to">Please specify which file to export to.\nWARNING: File will be overwritten if it exists.</string>
<string name="specify_file_to_export_secret_keys_to">Please specify which file to export to.\nWARNING: You are about to export SECRET keys.\nWARNING: File will be overwritten if it exists.</string>
<string name="key_deletion_confirmation">Do you really want to delete the key \'%s\'?\nYou can\'t undo this!</string>
<string name="key_deletion_confirmation_multi">Do you really want to delete all selected keys?\nYou can\'t undo this!</string>
<string name="secret_key_deletion_confirmation">Do you really want to delete the SECRET key \'%s\'?\nYou can\'t undo this!</string>

View File

@ -447,11 +447,11 @@ public class PgpKeyHelper {
}
default: {
algorithmStr = "???";
algorithmStr = "Unknown";
break;
}
}
return algorithmStr + ", " + keySize + "bit";
return algorithmStr + ", " + keySize + " bit";
}
public static String convertFingerprintToHex(byte[] fp) {
@ -510,7 +510,7 @@ public class PgpKeyHelper {
}
/**
* TODO: what is the difference to the other function?
* TODO: documentation
*
* @param keyId
* @return

View File

@ -94,7 +94,7 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
public void onClick(View v) {
Intent intentImportFromFile = new Intent(getActivity(), ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE);
startActivityForResult(intentImportFromFile, Id.request.import_from_qr_code);
startActivityForResult(intentImportFromFile, 0);
}
});

View File

@ -68,8 +68,9 @@ public class KeyListSecretActivity extends DrawerActivity {
return true;
case R.id.menu_key_list_secret_import:
Intent intentImport = new Intent(this, ImportKeysActivity.class);
startActivityForResult(intentImport, Id.request.import_from_qr_code);
Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE);
startActivityForResult(intentImportFromFile, 0);
return true;
default:

View File

@ -77,8 +77,6 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements CreateN
private Uri mDataUri;
private PGPPublicKey mPublicKey;
private TextView mName;
private TextView mEmail;
private TextView mComment;
@ -200,36 +198,16 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements CreateN
}
private void loadData(Uri dataUri) {
// TODO: don't use pubkey object, use database!!!
PGPPublicKeyRing ring = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, dataUri);
mPublicKey = ring.getPublicKey();
mKeyId.setText(PgpKeyHelper.shortifyFingerprint(PgpKeyHelper
.convertFingerprintToHex(mPublicKey.getFingerprint())));
String fingerprint = PgpKeyHelper.convertFingerprintToHex(mPublicKey.getFingerprint());
fingerprint = fingerprint.replace(" ", "\n");
mFingerprint.setText(fingerprint);
// TODO: get image with getUserAttributes() on key and then PGPUserAttributeSubpacketVector
Date expiryDate = PgpKeyHelper.getExpiryDate(mPublicKey);
if (expiryDate == null) {
mExpiry.setText(R.string.none);
} else {
mExpiry.setText(DateFormat.getDateFormat(getApplicationContext()).format(expiryDate));
}
mCreation.setText(DateFormat.getDateFormat(getApplicationContext()).format(
PgpKeyHelper.getCreationDate(mPublicKey)));
mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(mPublicKey));
mActionEncrypt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
long[] encryptionKeyIds = new long[] { mPublicKey.getKeyID() };
// TODO: don't get object here!!! solve this differently!
PGPPublicKeyRing ring = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(
ViewKeyActivity.this, mDataUri);
PGPPublicKey publicKey = ring.getPublicKey();
long[] encryptionKeyIds = new long[] { publicKey.getKeyID() };
Intent intent = new Intent(ViewKeyActivity.this, EncryptActivity.class);
intent.setAction(EncryptActivity.ACTION_ENCRYPT);
intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
@ -262,6 +240,9 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements CreateN
static final String[] KEYRING_PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID,
UserIds.USER_ID };
static final int KEYRING_INDEX_ID = 0;
static final int KEYRING_INDEX_MASTER_KEY_ID = 1;
static final int KEYRING_INDEX_USER_ID = 2;
static final String[] USER_IDS_PROJECTION = new String[] { UserIds._ID, UserIds.USER_ID,
UserIds.RANK, };
@ -271,8 +252,18 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements CreateN
static final String[] KEYS_PROJECTION = new String[] { Keys._ID, Keys.KEY_ID,
Keys.IS_MASTER_KEY, Keys.ALGORITHM, Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN,
Keys.CAN_ENCRYPT, };
Keys.CAN_ENCRYPT, Keys.CREATION, Keys.EXPIRY };
static final String KEYS_SORT_ORDER = Keys.RANK + " ASC";
static final int KEYS_INDEX_ID = 0;
static final int KEYS_INDEX_KEY_ID = 1;
static final int KEYS_INDEX_IS_MASTER_KEY = 2;
static final int KEYS_INDEX_ALGORITHM = 3;
static final int KEYS_INDEX_KEY_SIZE = 4;
static final int KEYS_INDEX_CAN_CERTIFY = 5;
static final int KEYS_INDEX_CAN_SIGN = 6;
static final int KEYS_INDEX_CAN_ENCRYPT = 7;
static final int KEYS_INDEX_CREATION = 8;
static final int KEYS_INDEX_EXPIRY = 9;
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
@ -310,7 +301,9 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements CreateN
switch (loader.getId()) {
case LOADER_ID_KEYRING:
if (data.moveToFirst()) {
String[] mainUserId = PgpKeyHelper.splitUserId(data.getString(2));
// get name, email, and comment from USER_ID
String[] mainUserId = PgpKeyHelper.splitUserId(data
.getString(KEYRING_INDEX_USER_ID));
setTitle(mainUserId[0]);
mName.setText(mainUserId[0]);
mEmail.setText(mainUserId[1]);
@ -322,6 +315,50 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements CreateN
mUserIdsAdapter.swapCursor(data);
break;
case LOADER_ID_KEYS:
// the first key here is our master key
if (data.moveToFirst()) {
// get key id from MASTER_KEY_ID
String keyId = "0x"
+ PgpKeyHelper.convertKeyIdToHex(data.getLong(KEYS_INDEX_KEY_ID));
mKeyId.setText(keyId);
if (data.isNull(KEYS_INDEX_CREATION)) {
mCreation.setText(R.string.none);
} else {
Date creationDate = new Date(data.getLong(KEYS_INDEX_CREATION) * 1000);
mCreation.setText(DateFormat.getDateFormat(getApplicationContext()).format(
creationDate));
}
if (data.isNull(KEYS_INDEX_EXPIRY)) {
mExpiry.setText(R.string.none);
} else {
Date expiryDate = new Date(data.getLong(KEYS_INDEX_EXPIRY) * 1000);
mExpiry.setText(DateFormat.getDateFormat(getApplicationContext()).format(
expiryDate));
}
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
data.getInt(KEYS_INDEX_ALGORITHM), data.getInt(KEYS_INDEX_KEY_SIZE));
mAlgorithm.setText(algorithmStr);
// TODO: Don't get key object here!!!
// put fingerprint in database?
PGPPublicKeyRing ring = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this,
mDataUri);
PGPPublicKey publicKey = ring.getPublicKey();
String fingerprint = PgpKeyHelper.convertFingerprintToHex(publicKey
.getFingerprint());
fingerprint = fingerprint.replace(" ", "\n");
mFingerprint.setText(fingerprint);
// TODO: get image with getUserAttributes() on key and then
// PGPUserAttributeSubpacketVector
}
mKeysAdapter.swapCursor(data);
break;

View File

@ -43,6 +43,7 @@ import android.widget.TextView;
public class KeyListPublicAdapter extends CursorAdapter implements StickyListHeadersAdapter {
private LayoutInflater mInflater;
private int mSectionColumnIndex;
private int mIndexUserId;
@SuppressLint("UseSparseArrays")
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
@ -52,6 +53,26 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
mInflater = LayoutInflater.from(context);
mSectionColumnIndex = sectionColumnIndex;
initIndex(c);
}
@Override
public Cursor swapCursor(Cursor newCursor) {
initIndex(newCursor);
return super.swapCursor(newCursor);
}
/**
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
* performance comparison see http://stackoverflow.com/a/17999582
*
* @param cursor
*/
private void initIndex(Cursor cursor) {
if (cursor != null) {
mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
}
}
/**
@ -62,14 +83,12 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknown_user_id);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = cursor.getString(userIdIndex);
String userId = cursor.getString(mIndexUserId);
if (userId != null) {
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);

View File

@ -37,6 +37,8 @@ import android.widget.TextView;
public class KeyListSecretAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private int mIndexUserId;
@SuppressLint("UseSparseArrays")
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
@ -44,18 +46,36 @@ public class KeyListSecretAdapter extends CursorAdapter {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
initIndex(c);
}
@Override
public Cursor swapCursor(Cursor newCursor) {
initIndex(newCursor);
return super.swapCursor(newCursor);
}
/**
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
* performance comparison see http://stackoverflow.com/a/17999582
*
* @param cursor
*/
private void initIndex(Cursor cursor) {
if (cursor != null) {
mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
}
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknown_user_id);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
mainUserIdRest.setText("");
String userId = cursor.getString(userIdIndex);
String userId = cursor.getString(mIndexUserId);
if (userId != null) {
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -40,6 +40,11 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private ListView mListView;
private int mIndexUserId;
private int mIndexMasterKeyId;
private int mIndexProjectionValid;
private int mIndexProjectionAvailable;
public final static String PROJECTION_ROW_AVAILABLE = "available";
public final static String PROJECTION_ROW_VALID = "valid";
@ -50,21 +55,45 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
mInflater = LayoutInflater.from(context);
mListView = listView;
mKeyType = keyType;
initIndex(c);
}
@Override
public Cursor swapCursor(Cursor newCursor) {
initIndex(newCursor);
return super.swapCursor(newCursor);
}
/**
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
* performance comparison see http://stackoverflow.com/a/17999582
*
* @param cursor
*/
private void initIndex(Cursor cursor) {
if (cursor != null) {
mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
mIndexMasterKeyId = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
mIndexProjectionValid = cursor.getColumnIndexOrThrow(PROJECTION_ROW_VALID);
mIndexProjectionAvailable = cursor.getColumnIndexOrThrow(PROJECTION_ROW_AVAILABLE);
}
}
public String getUserId(int position) {
mCursor.moveToPosition(position);
return mCursor.getString(mCursor.getColumnIndex(UserIds.USER_ID));
return mCursor.getString(mIndexUserId);
}
public long getMasterKeyId(int position) {
mCursor.moveToPosition(position);
return mCursor.getLong(mCursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
return mCursor.getLong(mIndexMasterKeyId);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
boolean valid = cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_VALID)) > 0;
boolean valid = cursor.getInt(mIndexProjectionValid) > 0;
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.unknown_user_id);
@ -75,7 +104,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
TextView status = (TextView) view.findViewById(R.id.status);
status.setText(R.string.unknown_status);
String userId = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
String userId = cursor.getString(mIndexUserId);
if (userId != null) {
String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
@ -85,7 +114,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
mainUserId.setText(userIdSplit[0]);
}
long masterKeyId = cursor.getLong(cursor.getColumnIndex(KeyRings.MASTER_KEY_ID));
long masterKeyId = cursor.getLong(mIndexMasterKeyId);
keyId.setText(PgpKeyHelper.convertKeyIdToHex(masterKeyId));
if (mainUserIdRest.getText().length() == 0) {
@ -99,7 +128,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
status.setText(R.string.can_sign);
}
} else {
if (cursor.getInt(cursor.getColumnIndex(PROJECTION_ROW_AVAILABLE)) > 0) {
if (cursor.getInt(mIndexProjectionAvailable) > 0) {
// has some CAN_ENCRYPT keys, but col(ROW_VALID) = 0, so must be revoked or
// expired
status.setText(R.string.expired);

View File

@ -33,19 +33,52 @@ import android.widget.TextView;
public class ViewKeyKeysAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private int mIndexKeyId;
private int mIndexAlgorithm;
private int mIndexKeySize;
private int mIndexIsMasterKey;
private int mIndexCanCertify;
private int mIndexCanEncrypt;
private int mIndexCanSign;
public ViewKeyKeysAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
initIndex(c);
}
@Override
public Cursor swapCursor(Cursor newCursor) {
initIndex(newCursor);
return super.swapCursor(newCursor);
}
/**
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
* performance comparison see http://stackoverflow.com/a/17999582
*
* @param cursor
*/
private void initIndex(Cursor cursor) {
if (cursor != null) {
mIndexKeyId = cursor.getColumnIndexOrThrow(Keys.KEY_ID);
mIndexAlgorithm = cursor.getColumnIndexOrThrow(Keys.ALGORITHM);
mIndexKeySize = cursor.getColumnIndexOrThrow(Keys.KEY_SIZE);
mIndexIsMasterKey = cursor.getColumnIndexOrThrow(Keys.IS_MASTER_KEY);
mIndexCanCertify = cursor.getColumnIndexOrThrow(Keys.CAN_CERTIFY);
mIndexCanEncrypt = cursor.getColumnIndexOrThrow(Keys.CAN_ENCRYPT);
mIndexCanSign = cursor.getColumnIndexOrThrow(Keys.CAN_SIGN);
}
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(cursor
.getColumnIndex(Keys.KEY_ID)));
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
String keyIdStr = "0x" + PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId));
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(cursor.getInt(mIndexAlgorithm),
cursor.getInt(mIndexKeySize));
TextView keyId = (TextView) view.findViewById(R.id.keyId);
keyId.setText(keyIdStr);
@ -54,28 +87,28 @@ public class ViewKeyKeysAdapter extends CursorAdapter {
keyDetails.setText("(" + algorithmStr + ")");
ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
if (cursor.getInt(mIndexIsMasterKey) != 1) {
masterKeyIcon.setVisibility(View.INVISIBLE);
} else {
masterKeyIcon.setVisibility(View.VISIBLE);
}
ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
if (cursor.getInt(mIndexCanCertify) != 1) {
certifyIcon.setVisibility(View.GONE);
} else {
certifyIcon.setVisibility(View.VISIBLE);
}
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
if (cursor.getInt(mIndexCanEncrypt) != 1) {
encryptIcon.setVisibility(View.GONE);
} else {
encryptIcon.setVisibility(View.VISIBLE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
if (cursor.getInt(mIndexCanSign) != 1) {
signIcon.setVisibility(View.GONE);
} else {
signIcon.setVisibility(View.VISIBLE);

View File

@ -31,17 +31,38 @@ import android.widget.TextView;
public class ViewKeyUserIdsAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private int mIndexUserId;
public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
initIndex(c);
}
@Override
public Cursor swapCursor(Cursor newCursor) {
initIndex(newCursor);
return super.swapCursor(newCursor);
}
/**
* Get column indexes for performance reasons just once in constructor and swapCursor. For a
* performance comparison see http://stackoverflow.com/a/17999582
*
* @param cursor
*/
private void initIndex(Cursor cursor) {
if (cursor != null) {
mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
}
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
String userIdStr = cursor.getString(userIdIndex);
String userIdStr = cursor.getString(mIndexUserId);
TextView userId = (TextView) view.findViewById(R.id.userId);
userId.setText(userIdStr);