Loader for email list

This commit is contained in:
str4d
2014-02-26 07:08:41 +00:00
parent dcfd6e8113
commit 89565df4fb
4 changed files with 263 additions and 5 deletions

View File

@@ -4,9 +4,16 @@ import java.util.List;
import android.content.Context;
import i2p.bote.email.AddressDisplayFilter;
import i2p.bote.email.Email;
import i2p.bote.email.EmailAttribute;
import i2p.bote.email.Identities;
import i2p.bote.fileencryption.PasswordException;
import i2p.bote.folder.EmailFolder;
public class BoteHelper {
private static AddressDisplayFilter ADDRESS_DISPLAY_FILTER;
public static EmailFolder getMailFolder(String folderName) {
List<EmailFolder> folders = I2PBote.getInstance().getEmailFolders();
for (EmailFolder folder : folders) {
@@ -37,4 +44,15 @@ public class BoteHelper {
else
return name;
}
public static List<Email> getEmails(EmailFolder folder, EmailAttribute sortColumn, boolean descending) throws PasswordException {
return folder.getElements(getAddressDisplayFilter(), sortColumn, descending);
}
private static AddressDisplayFilter getAddressDisplayFilter() throws PasswordException {
Identities identities = I2PBote.getInstance().getIdentities();
if (ADDRESS_DISPLAY_FILTER == null)
ADDRESS_DISPLAY_FILTER = new AddressDisplayFilter(identities, I2PBote.getInstance().getAddressBook());
return ADDRESS_DISPLAY_FILTER;
}
}

View File

@@ -0,0 +1,47 @@
package i2p.bote;
import java.util.List;
import javax.mail.MessagingException;
import i2p.bote.email.Email;
import i2p.bote.folder.EmailFolder;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class EmailListAdapter extends ArrayAdapter<Email> {
private final LayoutInflater mInflater;
public EmailListAdapter(Context context) {
super(context, android.R.layout.simple_list_item_2);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setData(List<Email> emails) {
clear();
if (emails != null) {
for (Email email : emails) {
add(email);
}
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = mInflater.inflate(R.layout.listitem_email, parent, false);
Email email = getItem(position);
TextView name = (TextView) v.findViewById(R.id.email_subject);
try {
name.setText(email.getSubject());
} catch (MessagingException e) {
name.setText("ERROR: " + e.getMessage());
}
return v;
}
}

View File

@@ -0,0 +1,155 @@
package i2p.bote;
import i2p.bote.email.Email;
import i2p.bote.fileencryption.PasswordException;
import i2p.bote.folder.EmailFolder;
import i2p.bote.folder.FolderListener;
import java.util.List;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
public class EmailListLoader extends AsyncTaskLoader<List<Email>> implements
FolderListener {
private EmailFolder mFolder;
private List<Email> mData;
public EmailListLoader(Context context, EmailFolder folder) {
super(context);
mFolder = folder;
}
@Override
public List<Email> loadInBackground() {
try {
return BoteHelper.getEmails(mFolder, null, false);
} catch (PasswordException pe) {
// TODO: Handle this error properly (get user to log in)
return null;
}
}
/**
* Called when there is new data to deliver to the client. The
* super class will take care of delivering it; the implementation
* here just adds a little more logic.
*/
@Override
public void deliverResult(List<Email> data) {
if (isReset()) {
// An async query came in while the loader is stopped. We
// don't need the result.
if (data != null) {
releaseResources(data);
}
}
// Hold a reference to the old data so it doesn't get garbage collected.
// We must protect it until the new data has been delivered.
List<Email> oldData = mData;
mData = data;
if (isStarted()) {
// If the Loader is currently started, we can immediately
// deliver its results.
super.deliverResult(data);
}
// Invalidate the old data as we don't need it any more.
if (oldData != null && oldData != data) {
releaseResources(oldData);
}
}
/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
if (mData != null) {
// Deliver any previously loaded data immediately.
deliverResult(mData);
}
// Start watching for changes in the folder
mFolder.addFolderListener(this);
if (takeContentChanged() || mData == null) {
// When the observer detects a change, it should call onContentChanged()
// on the Loader, which will cause the next call to takeContentChanged()
// to return true. If this is ever the case (or if the current data is
// null), we force a new load.
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
@Override
protected void onStopLoading() {
// The Loader is in a stopped state, so we should attempt to cancel the
// current load (if there is one).
cancelLoad();
// Note that we leave the observer as is. Loaders in a stopped state
// should still monitor the data source for changes so that the Loader
// will know to force a new load if it is ever started again.
}
/**
* Handles a request to completely reset the Loader.
*/
@Override
protected void onReset() {
super.onReset();
// Ensure the loader has been stopped.
onStopLoading();
// At this point we can release the resources associated with 'mData'.
if (mData != null) {
releaseResources(mData);
mData = null;
}
// Stop monitoring for changes.
mFolder.removeFolderListener(this);
}
/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(List<Email> data) {
// Attempt to cancel the current asynchronous load.
super.onCanceled(data);
// The load has been canceled, so we should release the resources
// associated with 'data'.
releaseResources(data);
}
/**
* Helper function to take care of releasing resources associated
* with an actively loaded data set.
*/
private void releaseResources(List<Email> data) {
// For a simple List, there is nothing to do. For something like a Cursor, we
// would close it in this method. All resources associated with the Loader
// should be released here.
}
// FolderListener
@Override
public void elementAdded() {
onContentChanged();
}
@Override
public void elementRemoved() {
onContentChanged();
}
}

View File

@@ -1,12 +1,23 @@
package i2p.bote;
import java.util.List;
import i2p.bote.email.Email;
import i2p.bote.folder.EmailFolder;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
public class FolderFragment extends ListFragment {
public class FolderFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<List<Email>> {
public static final String FOLDER_NAME = "folder_name";
private static final int EMAIL_LIST_LOADER = 1;
private EmailListAdapter mAdapter;
private EmailFolder mFolder;
public static FolderFragment newInstance(String folderName) {
FolderFragment f = new FolderFragment();
Bundle args = new Bundle();
@@ -16,10 +27,37 @@ public class FolderFragment extends ListFragment {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAdapter = new EmailListAdapter(getActivity());
String folderName = getArguments().getString(FOLDER_NAME);
EmailFolder folder = BoteHelper.getMailFolder(folderName);
mFolder = BoteHelper.getMailFolder(folderName);
setListAdapter(mAdapter);
setListShown(false);
if (mFolder != null)
getLoaderManager().initLoader(EMAIL_LIST_LOADER, null, this);
}
// LoaderManager.LoaderCallbacks<List<Email>>
public Loader<List<Email>> onCreateLoader(int id, Bundle args) {
return new EmailListLoader(getActivity(), mFolder);
}
public void onLoadFinished(Loader<List<Email>> loader,
List<Email> data) {
mAdapter.setData(data);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
public void onLoaderReset(Loader<List<Email>> loader) {
mAdapter.setData(null);
}
}