Loader for email list
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
47
src/i2p/bote/EmailListAdapter.java
Normal file
47
src/i2p/bote/EmailListAdapter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
155
src/i2p/bote/EmailListLoader.java
Normal file
155
src/i2p/bote/EmailListLoader.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user