It seems that there is a bug in the Support library v4, I want to access the MediaStore Audio using CursorLoader and LoaderManager and I have followed the protocol to the T, and no matter what I do, OnLoaderFinished is not called.
Here are some code snippets, I created something I called MediaStoreInterface,
the relevant parts of MediaStoreInterface are as follows:
public class MediaStoreInterface extends Observable
{
protected Cursor cursor;
protected static final int LOADER_ID1 = 1;
protected static final int LOADER_ID2 = 2;
protected static int lastLoaderId = 0;
protected static String function = "SONGS";
protected static PaudioActivity act;
protected static Sound selectedSound = null;
protected static final String[] projections = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DATA};
protected static final String[] projectionsPlaylist = {MediaStore.Audio.Playlists._ID,MediaStore.Audio.Playlists.NAME};
protected static final Uri sourceUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
protected static final Uri uriPlaylists = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
protected static ArrayList<String> ret;
protected static boolean done = false;
//Singleton
protected static MediaStoreInterface ref = null;
public static MediaStoreInterface getMusicLibrary(Activity act_)
{
if (ref == null)
ref = new MediaStoreInterface(act_);
return ref;
}
protected MediaStoreInterface(Activity act_)
{
act = (PaudioActivity) act_;
}
public static MediaStoreInterface getMSI()
{
if (android.os.Build.VERSION.SDK_INT < 11)
return MediaStoreInterfaceFrodo.getMusicLibrary(act);
else
return MediaStoreInterfaceHoneyComb.getMusicLibrary(act);
}
protected void loadArray(Cursor data)
{
int num = data.getColumnCount();
if (data == null || !data.moveToFirst())
return;
while(!data.isLast())
{
String s = data.getString(0);
int col = 1;
while(col < num)
s += "|" + data.getString(col++);
ret.add(s);
data.moveToNext();
}
if (function == "SONGS")
numSongs = ret.size();
if (function == "PLAYLISTS")
numPlaylists = ret.size();
cursor = data;
}
public static void setDone()
{
done = true;
}
}
It's a Singleton, that is supposed to return the right MediaStoreInterface for each API,
I extend Frodo from this, as follows:
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.content.Loader.OnLoadCompleteListener;
public class MediaStoreInterfaceFrodo extends MediaStoreInterface implements LoaderManager.LoaderCallbacks<Cursor>, OnLoadCompleteListener<Cursor>
{
public static MediaStoreInterface getMusicLibrary(Activity act_)
{
if (ref == null)
ref = new MediaStoreInterfaceFrodo(act_);
return ref;
}
public void setPaudioActivity(PaudioActivity act_)
{
act = act_;
}
protected MediaStoreInterfaceFrodo(Activity act_)
{
super(act_);
}
public ArrayList<String> getSongList()
{
function = "SONGS";
done = false;
if (ret == null)
ret = new ArrayList<String>();
else
ret.clear();
lastLoaderId = LOADER_ID1;
LoaderManager lm = act.getSupportLoaderManager();
Loader<Cursor> loader1 = lm.getLoader(LOADER_ID1);
if (loader1 != null && loader1.isReset())
loader1 = lm.restartLoader(LOADER_ID1, null, this);
else
{
loader1 = lm.initLoader(LOADER_ID1, null, this);
}
while(!done)
{
waitabit();
}
return ret;
}
public static void editSelectedSongTitle(String newtitle)
{
// TODO Auto-generated method stub
}
public static void setContinuePlayMode(PlayMode pm_)
{
pm = pm_;
}
public List<String> getPlayListNames()
{
function = "PLAYLISTS";
done = false;
if (ret == null)
ret = new ArrayList<String>();
else
ret.clear();
lastLoaderId = LOADER_ID2;
LoaderManager lm = act.getSupportLoaderManager();
lm.initLoader(LOADER_ID2, null, this);
while(!done)
{
waitabit();
}
function = "SONGS";
return ret;
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1)
{
CursorLoader cursorLoader = null;
switch (id)
{
case LOADER_ID1:
cursorLoader = new CursorLoader(act, sourceUri, projections, null, null, MediaStore.Audio.Media.TITLE);
break;
case LOADER_ID2:
cursorLoader = new CursorLoader(act, uriPlaylists, projectionsPlaylist, null, null, MediaStore.Audio.Playlists.NAME);
break;
default:
break;
}
cursorLoader.forceLoad();
return cursorLoader;
}
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data)
{
cursor = data;
loadArray(cursor);
done = true;
}
#Override
public void onLoaderReset(Loader<Cursor> arg0)
{
act.getSupportLoaderManager().restartLoader(lastLoaderId, null, ( android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor>) this);
}
#Override
public void onLoadComplete(Loader<Cursor> loader, Cursor data)
{
onLoadFinished( loader, data);
}
}
I have tried to separate the database query from the usual nukes and crannies of my activity, long story short I have a button that if one clicks, getSongList is called,
I also have setActivity to turn the act member into the calling Activity,
I have read ALL relevant StackOverflow articles and everything on android development site. Some of you might object that I have to call some of my functions on the UI thread, I have done that too, to no avail. I have implemented the same set of code, in my main Activity, but still no matter what I do. OnLoadFinished is never called.
I'm unsure what is causing the problem, as your code is incomplete, however your imports imply you might not use the activity from the support package:
import android.app.Activity;
should be
import android.support.v4.app.FragmentActivity;
i actually don't see how your code could even compile, as the non-support-activity doesn't have a method called getSupportLoaderManager()
without knowing what the actual problem is, i'll post a sample i just created, i boiled down the code to what is actually necessary. Note however that you don't have to implement the LoaderCallback in an activity. This code is working, as i tested it.
package com.suhw.samples.mediastore;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
public class QueryMediaStoreActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private final static String TAG = "QueryMediaStoreActivity";
private static final int LOADER_ID1 = 1;
private static final String[] audioMediaProjection = {MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.DATA};
private static final Uri audioMediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LoaderManager loaderManager = getSupportLoaderManager();
loaderManager.initLoader(LOADER_ID1, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
switch (id) {
case LOADER_ID1:
return new CursorLoader(this, audioMediaUri, audioMediaProjection, null, null, MediaStore.Audio.Media.TITLE);
default:
return null;
}
}
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
switch (cursorLoader.getId()) {
case LOADER_ID1:
Log.d(TAG, "onLoadFinished called:\n\tcursorCount:" + cursor.getCount());
break;
}
}
#Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
}
}
Change your OncreateLoader(), If dealing with multiple Loader then better use switch() statement.
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1)
{
CursorLoader cursorLoader = null;
switch (id) {
case LOADER_ID1:
cursorLoader = new CursorLoader(getActivity(), sourceUri, projections, null, null, MediaStore.Audio.Media.TITLE);
break;
case LOADER_ID2:
cursorLoader = new CursorLoader(getActivity(), uriPlaylists, projectionsPlaylist, null, null, MediaStore.Audio.Playlists.NAME);
break;
default:
break;
}
cursorLoader.forceLoad();
return cursorLoader;
}
Edit:-
Use getActivity() instead of act for details CursorLoader
Note:-
The method getLoaderManager() is only available in the Fragment class. To get a LoaderManager in a FragmentActivity, call getSupportLoaderManager().
Try like this.
Related
I didn't find any solution in the Internet, only a tutorial on Android Developers, which unfortunately gives only a small part of code needed for it. I ended up having something like this:
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.Data;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
// Defines the selection clause
private static final String SELECTION = Data.LOOKUP_KEY + " = ?"; // Defines the array to hold the search criteria
private String[] mSelectionArgs = { "" };
private String mLookupKey;
private static final String SORT_ORDER = Data.MIMETYPE;
final int DETAILS_QUERY_ID = 0;
private static final String PROJECTION[] = {
Data._ID, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5, Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11, Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// getLoaderManager().initLoader(DETAILS_QUERY_ID, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
switch (loaderId) {
case DETAILS_QUERY_ID:
// Assigns the selection parameter
mSelectionArgs[0] = mLookupKey; // Starts the query
CursorLoader mLoader = new CursorLoader(this, Data.CONTENT_URI, PROJECTION,
SELECTION, mSelectionArgs, SORT_ORDER);
}
return null; // TODO what should be here ?
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
// switch (loader.getId()) {
// case DETAILS_QUERY_ID:
// }
// break;
// }
}
}
How can I make it work ? https://developer.android.com/training/contacts-provider/retrieve-details.html is really lacking some code and explanation
I'm having trouble starting a task after it has been cancelled the first time. It will run when entering the view, and starting the task, then cancel works when the fragment is first destroyed. But when re-entering the view, the AsyncTask will no longer run.
Is it possible some class state that needs to be cleaned up? Or do I need to remove the Fragment with the AsyncTask from the back stack?
Here is my code below:
package com.emijit.lighteningtalktimer;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.emijit.lighteningtalktimer.data.Timer;
import com.emijit.lighteningtalktimer.data.TimerContract.TimerEntry;
public class RunTimerFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String LOG_TAG = RunTimerFragment.class.getSimpleName();
private View rootView;
private Uri mUri;
private long mTimerId = 0;
private Timer mTimer;
private RunTimerTask mRunTimerTask;
private static final int DETAIL_LOADER = 0;
public static String URI = "URI";
public RunTimerFragment() {
}
static class ViewHolder {
TextView intervals;
TextView timerSeconds;
TextView timerMinutes;
TextView timerHours;
public ViewHolder(View view) {
intervals = (TextView) view.findViewById(R.id.run_timer_intervals);
timerSeconds = (TextView) view.findViewById(R.id.timer_seconds);
timerMinutes = (TextView) view.findViewById(R.id.timer_minutes);
timerHours = (TextView) view.findViewById(R.id.timer_hours);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_run_timer, container, false);
ViewHolder viewHolder = new ViewHolder(rootView);
rootView.setTag(viewHolder);
Bundle arguments = getArguments();
if (arguments != null) {
mUri = arguments.getParcelable(URI);
if (mUri != null) {
mTimerId = ContentUris.parseId(mUri);
Log.d(LOG_TAG, "mTimerId: " + mTimerId);
}
}
return rootView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(DETAIL_LOADER, null, this);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (mTimerId != 0) {
return new CursorLoader(
getActivity(),
TimerEntry.CONTENT_URI,
null,
TimerEntry._ID + " = ?",
new String[] { Long.toString(mTimerId) },
null
);
}
return null;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if (cursor != null && cursor.moveToFirst()) {
mTimer = new Timer(cursor);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
}
public void startTimer() {
mRunTimerTask = new RunTimerTask();
mRunTimerTask.execute(mTimer);
}
#Override
public void onPause() {
super.onPause();
mRunTimerTask.cancel(true);
}
private class RunTimerTask extends AsyncTask<Timer, Integer, Long> {
private final String LOG_TAG = RunTimerTask.class.getSimpleName();
Timer mTimer;
int mCurrentSeconds = 0;
int mCurrentIntervals = 0;
#Override
protected Long doInBackground(Timer... params) {
Log.d(LOG_TAG, "doInBackground");
mTimer = params[0];
while (mTimer.getIntervals() > mCurrentIntervals) {
try {
Thread.sleep(1000);
mCurrentSeconds++;
publishProgress(mCurrentSeconds);
} catch (InterruptedException e) {
Log.d(LOG_TAG, e.toString());
}
}
return (long) mCurrentIntervals;
}
#Override
protected void onProgressUpdate(Integer... values) {
// do stuff
}
#Override
protected void onPostExecute(Long aLong) {
super.onPostExecute(aLong);
Log.d(LOG_TAG, "onPostExecute");
}
}
}
I think the issue might be in the catch block. Not sure about the mTimer.getIntervals() because it's from third party.
When you cancel the task. The InterruptedException will be caught in the task thread. Then your loop will still keep going because you didn't return or break the loop.
Since all AsyncTask will be queued up in one thread pool of size 1, even if you start another AsyncTask, it will still be blocked.
In your sample, I cannot see any call to startTimer(). Should you be overiding onResume() and calling startTimer() in there?
I've created demo application which insert some data into sqlite database and update on listview [Fragment]. But i want to add one another data by click on button which data comes from EditText and update on listview with new data.
I write my demo code below. pls let me know how do i show all data in listview which after adding into database at the same time.
####################################### Step 1
package com.example.locationsample.database;
import java.util.List;
import android.database.sqlite.SQLiteDatabase;
public abstract class DataSource<T> {
public final SQLiteDatabase mDatabase;
public DataSource(final SQLiteDatabase database) {
mDatabase = database;
}
public abstract boolean insert(T entity);
public abstract boolean delete(T entity);
public abstract boolean update(T entity);
public abstract List read();
public abstract List read(String selection, String[] selectionArgs,
String groupBy, String having, String orderBy);
}
####################################### Step 2
package com.example.locationsample.model;
public class Test {
public Test() {
}
public Test(String name) {
this.name = name;
}
private int id;
private String name;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id
* the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name
* the name to set
*/
public void setName(final String name) {
this.name = name;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
return name;
// return "Test [name=" + name + "]";
}
}
####################################### Step 3
package com.example.locationsample.database;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.example.locationsample.model.Test;
public class TestDataSource extends DataSource<Test> {
public static final String TABLE_NAME = "test";
private static final String COLUMN_ID = "_id";
private static final String COLUMN_NAME = "name";
public static final String CREATE_COMMAND = "create table " + TABLE_NAME
+ " (" + COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_NAME + " text not null);";
public TestDataSource(final SQLiteDatabase database) {
super(database);
}
#Override
public boolean insert(final Test entity) {
if (entity == null) {
return false;
}
final long result = mDatabase.insert(TABLE_NAME, null,
generateContentValueFromObject(entity));
return result != -1;
}
#Override
public boolean delete(final Test entity) {
if (entity == null) {
return false;
}
final int result = mDatabase.delete(TABLE_NAME, COLUMN_ID + "=?",
new String[] { String.valueOf(entity.getId()) });
return result != 0;
}
#Override
public boolean update(final Test entity) {
if (entity == null) {
return false;
}
final int result = mDatabase.update(TABLE_NAME,
generateContentValueFromObject(entity), COLUMN_ID + "=?",
new String[] { String.valueOf(entity.getId()) });
return result != 0;
}
#Override
public List<Test> read() {
final Cursor cursor = mDatabase.query(TABLE_NAME, getAllColumns(),
null, null, null, null, null);
final List<Test> tests = new ArrayList<Test>();
if (cursor != null && cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
tests.add(generateObjectFromCursor(cursor));
cursor.moveToNext();
}
cursor.close();
}
return tests;
}
#Override
public List<Test> read(final String selection,
final String[] selectionArgs, final String groupBy,
final String having, final String orderBy) {
final Cursor cursor = mDatabase.query(TABLE_NAME, getAllColumns(),
selection, selectionArgs, groupBy, having, orderBy);
final List<Test> tests = new ArrayList<Test>();
if (cursor != null && cursor.moveToFirst()) {
while (!cursor.isAfterLast()) {
tests.add(generateObjectFromCursor(cursor));
cursor.moveToNext();
}
cursor.close();
}
return tests;
}
private String[] getAllColumns() {
return new String[] { COLUMN_ID, COLUMN_NAME };
}
private Test generateObjectFromCursor(final Cursor cursor) {
if (cursor == null) {
return null;
}
final Test test = new Test();
test.setId(cursor.getInt(cursor.getColumnIndex(COLUMN_ID)));
test.setName(cursor.getString(cursor.getColumnIndex(COLUMN_NAME)));
return test;
}
private ContentValues generateContentValueFromObject(final Test entity) {
if (entity == null) {
return null;
}
final ContentValues values = new ContentValues();
values.put(COLUMN_NAME, entity.getName());
return values;
}
}
####################################### Step 4
package com.example.locationsample.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DbHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "test.db";
private static final int DATABASE_VERSION = 1;
public DbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TestDataSource.CREATE_COMMAND);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TestDataSource.TABLE_NAME);
onCreate(db);
}
}
####################################### Step 5
package com.example.locationsample.loader;
import android.content.Loader;
import android.os.AsyncTask;
import android.util.Log;
public abstract class ContentChangingTask<T1, T2, T3> extends
AsyncTask<T1, T2, T3> {
private static final String TAG = "ContentChangingTask";
private Loader<?> mLoader = null;
public ContentChangingTask(final Loader<?> loader) {
mLoader = loader;
}
#Override
protected void onPostExecute(final T3 result) {
// super.onPostExecute(result);
Log.i(TAG, "+++ onPostExecute() called! +++");
mLoader.onContentChanged();
}
}
####################################### Step 6
package com.example.locationsample.loader;
import java.util.List;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.util.Log;
public abstract class AbstractDataLoader<E extends List<?>> extends
AsyncTaskLoader<E> {
private static final String TAG = "AbstractDataLoader";
protected E mLastDataList = null;
protected abstract E buildList();
public AbstractDataLoader(final Context context) {
super(context);
}
/**
* Runs on a worker thread, loading in our data. Delegates the real work to
* concrete subclass' buildList() method.
*/
#Override
public E loadInBackground() {
Log.d(TAG, "+++ loadInBackground() called! +++");
return buildList();
}
/**
* Runs on the UI thread, routing the results from the background thread to
* whatever is using the dataList.
*/
#Override
public void deliverResult(final E dataList) {
Log.d(TAG, "+++ deliverResult() called! +++");
if (isReset()) {
// An async query came in while the loader is stopped
emptyDataList(dataList);
return;
}
final E oldDataList = mLastDataList;
mLastDataList = dataList;
if (isStarted()) {
super.deliverResult(dataList);
}
if (oldDataList != null && oldDataList != dataList
&& oldDataList.size() > 0) {
emptyDataList(oldDataList);
}
}
/**
* Starts an asynchronous load of the list data. When the result is ready
* the callbacks will be called on the UI thread. If a previous load has
* been completed and is still valid the result may be passed to the
* callbacks immediately.
*
* Must be called from the UI thread.
*/
#Override
protected void onStartLoading() {
//super.onStartLoading();
Log.d(TAG, "+++ onStartLoading() called! +++");
if (mLastDataList != null) {
deliverResult(mLastDataList);
}
if (takeContentChanged() || mLastDataList == null
|| mLastDataList.size() == 0) {
forceLoad();
}
}
/**
* Must be called from the UI thread, triggered by a call to stopLoading().
*/
#Override
protected void onStopLoading() {
Log.d(TAG, "+++ onStopLoading() called! +++");
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Must be called from the UI thread, triggered by a call to cancel(). Here,
* we make sure our Cursor is closed, if it still exists and is not already
* closed.
*/
#Override
public void onCanceled(final E dataList) {
Log.d(TAG, "+++ onCanceled() called! +++");
if (dataList != null && dataList.size() > 0) {
emptyDataList(dataList);
}
}
/**
* Must be called from the UI thread, triggered by a call to reset(). Here,
* we make sure our Cursor is closed, if it still exists and is not already
* closed.
*/
#Override
protected void onReset() {
super.onReset();
Log.d(TAG, "+++ onReset() called! +++");
// Ensure the loader is stopped
onStopLoading();
if (mLastDataList != null && mLastDataList.size() > 0) {
emptyDataList(mLastDataList);
}
mLastDataList = null;
}
protected void emptyDataList(final E dataList) {
if (dataList != null && dataList.size() > 0) {
for (int i = 0; i < dataList.size(); i++) {
dataList.remove(i);
}
}
}
}
####################################### Step 7
package com.example.locationsample.loader;
import java.util.List;
import android.content.Context;
import android.util.Log;
import com.example.locationsample.database.DataSource;
import com.example.locationsample.model.Test;
public class SQLiteTestDataLoader extends AbstractDataLoader<List<Test>> {
private static final String TAG = "SQLiteTestDataLoader";
private final DataSource<Test> mDataSource;
private String mSelection;
private String[] mSelectionArgs;
private String mGroupBy;
private String mHaving;
private String mOrderBy;
public SQLiteTestDataLoader(final Context context,
final DataSource<Test> dataSource, final String selection,
final String[] selectionArgs, final String groupBy,
final String having, final String orderBy) {
super(context);
mDataSource = dataSource;
}
#SuppressWarnings("unchecked")
#Override
protected List<Test> buildList() {
final List<Test> testList = mDataSource.read(mSelection,
mSelectionArgs, mGroupBy, mHaving, mOrderBy);
return testList;
}
public void insert(final Test entity) {
new InsertTask(this).execute(entity);
}
public void update(final Test entity) {
new UpdateTask(this).execute(entity);
}
public void delete(final Test entity) {
new DeleteTask(this).execute(entity);
}
private class InsertTask extends ContentChangingTask<Test, Void, Void> {
InsertTask(final SQLiteTestDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(final Test... params) {
Log.i(TAG, "+++ Inserting... +++");
mDataSource.insert(params[0]);
return (null);
}
}
private class UpdateTask extends ContentChangingTask<Test, Void, Void> {
UpdateTask(final SQLiteTestDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(final Test... params) {
Log.i(TAG, "+++ Updating... +++");
mDataSource.update(params[0]);
return (null);
}
}
private class DeleteTask extends ContentChangingTask<Test, Void, Void> {
DeleteTask(final SQLiteTestDataLoader loader) {
super(loader);
}
#Override
protected Void doInBackground(final Test... params) {
Log.i(TAG, "+++ Deleting... +++");
mDataSource.delete(params[0]);
return (null);
}
}
}
####################################### Step 8
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="#+id/txt_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<EditText
android:id="#+id/edtxt_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toLeftOf="#+id/btn_add"
android:inputType="text"
android:labelFor="#+id/edtxt_add" />
<Button
android:id="#+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="ADD" />
<fragment
android:id="#+id/titles"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/btn_add"
android:layout_below="#id/txt_data"
class="com.example.locationsample.MainFragment" />
</RelativeLayout>
####################################### Step 9
package com.example.locationsample;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;
import com.example.locationsample.database.DbHelper;
import com.example.locationsample.database.TestDataSource;
import com.example.locationsample.loader.SQLiteTestDataLoader;
import com.example.locationsample.model.Test;
import com.example.locationsample.utilities.Utils;
public class MainActivity extends Activity implements
OnClickListener {
private static final String TAG = "MainActivity";
private TextView mTxtData;
private EditText mEdTxtAdd;
private LocationManager mLocationManager;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxtData = (TextView) findViewById(R.id.txt_data);
mEdTxtAdd = (EditText) findViewById(R.id.edtxt_add);
findViewById(R.id.btn_add).setOnClickListener(this);
DbHelper helper = new DbHelper(MainActivity.this);
SQLiteDatabase database = helper.getWritableDatabase();
TestDataSource dataSource = new TestDataSource(database);
List<Test> testList = dataSource.read();
if (testList == null || testList.size() == 0) {
dataSource.insert(new Test("11111"));
dataSource.insert(new Test("22222"));
dataSource.insert(new Test("33333"));
}
database.close();
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_add:
if (mEdTxtAdd == null
|| TextUtils.isEmpty(mEdTxtAdd.getText().toString())) {
return;
}
DbHelper helper = new DbHelper(MainActivity.this);
SQLiteDatabase database = helper.getWritableDatabase();
TestDataSource dataSource = new TestDataSource(database);
SQLiteTestDataLoader loader = new SQLiteTestDataLoader(
MainActivity.this, dataSource, null, null, null, null, null);
loader.insert(new Test(mEdTxtAdd.getText().toString()));
break;
default:
break;
}
}
}
####################################### Step 10
package com.example.locationsample;
import java.util.List;
import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Loader;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import com.example.locationsample.database.DbHelper;
import com.example.locationsample.database.TestDataSource;
import com.example.locationsample.loader.SQLiteTestDataLoader;
import com.example.locationsample.model.Test;
public class MainFragment extends ListFragment implements
LoaderCallbacks<List<Test>> {
private ArrayAdapter<Test> mAdapter;
// The Loader's id (this id is specific to the ListFragment's LoaderManager)
private static final int LOADER_ID = 1;
private static final boolean DEBUG = true;
private static final String TAG = "MainFragment";
private SQLiteDatabase mDatabase;
private TestDataSource mDataSource;
private DbHelper mDbHelper;
#Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mDbHelper = new DbHelper(getActivity());
mDatabase = mDbHelper.getWritableDatabase();
mDataSource = new TestDataSource(mDatabase);
mAdapter = new ArrayAdapter<Test>(getActivity(),
android.R.layout.simple_list_item_1);
setEmptyText("No data, please add from menu.");
setListAdapter(mAdapter);
setListShown(false);
if (DEBUG) {
Log.i(TAG, "+++ Calling initLoader()! +++");
if (getLoaderManager().getLoader(LOADER_ID) == null) {
Log.i(TAG, "+++ Initializing the new Loader... +++");
} else {
Log.i(TAG,
"+++ Reconnecting with existing Loader (id '1')... +++");
}
}
// Initialize a Loader with id '1'. If the Loader with this id already
// exists, then the LoaderManager will reuse the existing Loader.
getLoaderManager().initLoader(LOADER_ID, null, this);
}
#Override
public Loader<List<Test>> onCreateLoader(final int id, final Bundle arg1) {
final SQLiteTestDataLoader loader = new SQLiteTestDataLoader(
getActivity(), mDataSource, null, null, null, null, null);
return loader;
}
#Override
public void onLoadFinished(final Loader<List<Test>> loader,
final List<Test> data) {
Log.d(TAG, "+++### onLoadFinished() called! ###+++");
if (DEBUG)
Log.i(TAG, "+++ onLoadFinished() called! +++");
mAdapter.clear();
for (final Test test : data) {
mAdapter.add(test);
}
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
#Override
public void onLoaderReset(final Loader<List<Test>> arg0) {
Log.i(TAG, "+++ onLoadReset() called! +++");
mAdapter.clear();
}
#Override
public void onDestroy() {
super.onDestroy();
mDbHelper.close();
mDatabase.close();
mDataSource = null;
mDbHelper = null;
mDatabase = null;
}
}
#
Whenever i write something in edittext and click on Add button, it stores data only to database, But it doesn't any update into listview which we are showing at there.
Pls, check where do i mistake???
Add this line in the main activity inside the onClick
getLoaderManager().restartLoader(0,null,this);
I've got this problem where when I change the orientation of my device, for some reason the on-screen representation of the ListView associated with my ListFragment is retained, and a new ListView is inflated beneath it. To give you some context, I am creating a very simple app whose purpose is to test some DAO objects I created. I would have preferred to post some screenshots depicting the behavior my app is experiencing, but unfortunately, my reputation is too low at the moment.
The best I could describe it would be that when I change the orientation of the device from portrait to landscape (and vice versa), it inflates a whole new ListView without deflating the previous one. I have been looking into this for a couple of days now, and quite honestly, I am stumped. Any help you guys could offer would be greatly appreciated.
Here is the code for the ListFragment:
package edu.uark.csce.mobile.healthyshopper;
import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
/**
* A fragment representing a list of Items.
* <p />
* <p />
* Activities containing this fragment MUST implement the {#link Callbacks}
* interface.
*/
public class ViewFragment extends ListFragment implements
LoaderCallbacks<Cursor> {
// Class Fields:
private static final String TAG = "healthyshopper.ViewFragment";
private static final int MAIN_DB_LOADER = 0;
// In the final application, any query to the main database needs to return
// at least these fields:
private final String[] NECESSARY_COLUMNS = { DAOContentProvider.FOOD_DES,
DAOContentProvider.FOOD_CALORIES, DAOContentProvider.FOOD_FAT,
DAOContentProvider.FOOD_CARBS, DAOContentProvider.FOOD_PROTEIN };
private final String FROM[] = {DAOContentProvider.FOOD_GROUP, DAOContentProvider.FOOD_DES,
DAOContentProvider.FOOD_MANUFAC, DAOContentProvider.FOOD_PROTEIN,
DAOContentProvider.FOOD_FAT, DAOContentProvider.FOOD_CARBS,
DAOContentProvider.FOOD_CALORIES, DAOContentProvider.FOOD_SERV_SIZE};
private final int TO[] = {R.id.fd_group, R.id.shrt_desc,
R.id.manufac, R.id.protein,
R.id.fat, R.id.carb,
R.id.cal, R.id.amt};
private int threadMode;
private int queryType;
private int foodGroupId;
private CursorLoader loader;
private SimpleCursorAdapter listAdapter;
// Preference Option Constants:
private int UI_THREAD = 0;
private int BRANCHED_THREAD = 1;
private int ALL_ROWS = 0;
private int SPECIFIC_FD_GROUP = 1;
private int LIMITED_ROWS = 2;
private OnFragmentInteractionListener mListener;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ViewFragment() {
}
/***************************************
* Life cycle callbacks:
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "in onCreate()");
setRetainInstance(true);
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
if(savedInstanceState == null){
listAdapter = new SimpleCursorAdapter(getActivity(), R.layout.list_node, null, FROM, TO, 0);
setListAdapter(listAdapter);
}
}
#Override
public void onStart(){
super.onStart();
}
#Override
public void onResume(){
super.onResume();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()
.getApplicationContext());
Log.d(TAG, preferences.getString("THREADING_MODE", "BLANK"));
//Load testing preferences:
threadMode = Integer.valueOf(preferences.getString("THREADING_MODE","0"));
queryType = Integer.valueOf(preferences.getString("QUERY_TYPE", "0"));
foodGroupId = Integer.valueOf(preferences.getString("FOOD_GROUP", "0")); // Default
if (threadMode == BRANCHED_THREAD) {
loader = (CursorLoader) getLoaderManager().initLoader(
MAIN_DB_LOADER, null, this);
} else {
String[] projection = null;
String selection = null;
if (queryType == SPECIFIC_FD_GROUP) {
Log.d(TAG, "Query Type: " + (getResources().getStringArray(R.array.query_type_select))[queryType]);
selection = DAOContentProvider.FOOD_GROUP + " = " + foodGroupId;
} else if (queryType == LIMITED_ROWS) {
projection = NECESSARY_COLUMNS;
}
/*This is for testing only. Ordinarily, you should NEVER perform Db operations on the UI thread.*/
listAdapter.swapCursor(getActivity().getContentResolver().query(
DAOContentProvider.CONTENT_URI, projection, selection, null, null));
}
}
#Override
public void onPause(){
super.onPause();
}
#Override
public void onStop(){
super.onStop();
}
#Override
public void onDestroyView(){
super.onDestroyView();
Log.e(TAG, "in onDestroyView()");
setListAdapter(null);
listAdapter.swapCursor(null);
listAdapter = null;
}
#Override
public void onDestroy(){
super.onDestroy();
}
#Override
public void onDetach(){
super.onDetach();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
if (null != mListener) {
}
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated to
* the activity and potentially other fragments contained in that activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(String id);
}
/**
* LoaderManager Callbacks;
*/
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case MAIN_DB_LOADER:
String[] projection = null;
String selection = null;
if (queryType == SPECIFIC_FD_GROUP) {
Log.d(TAG,
"Query Type: "
+ (getResources()
.getStringArray(R.array.query_type_select))[queryType]);
selection = DAOContentProvider.FOOD_GROUP + " = " + foodGroupId;
} else if (queryType == LIMITED_ROWS) {
projection = NECESSARY_COLUMNS;
}
return new CursorLoader(getActivity(),
DAOContentProvider.CONTENT_URI, projection, selection,
null, null);
default:
return null;
}
}
#Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
listAdapter.swapCursor(arg1);
listAdapter.notifyDataSetChanged();
}
#Override
public void onLoaderReset(Loader<Cursor> arg0) {
listAdapter.swapCursor(null);
listAdapter.notifyDataSetChanged();
}
}
And here is the code for its associated Activity:
package edu.uark.csce.mobile.healthyshopper;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class TestingActivity extends Activity implements ViewFragment.OnFragmentInteractionListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_testing);
ViewFragment list = new ViewFragment();
getFragmentManager().beginTransaction().add(R.id.test_layout, list).commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.testing, menu);
return true;
}
#Override
public void onFragmentInteraction(String id) {
// TODO Auto-generated method stub
}
}
You're using setRetainInstance(true); in your fragment. This makes the fragment to be retained and reused when the activity is re-created.
You can read more detailed description in this question: Further understanding setRetainInstance(true)
I'm using customized ListView in android, and using search with customized EditText. When I search for a name, I will get the result using getFilter().filter(cs);. But, when I rotate, the ListView shows the full list (without filtering), then after a delay, it shows the filtered list.
When I rotate without filtering, it maintains the listview position.
So I have to maintain the filtered ListView when I rotate the screen.
Please help. Thanks in advance...
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.Context;
import android.content.Loader;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
#SuppressLint("HandlerLeak")
public class ContactsListActivity
extends Activity
implements LoaderManager.LoaderCallbacks<ArrayList<ListViewItem>> {
private LetterScrollListView mLSListView;
private ProgressBar mProgressBar;
private EditText mSearchText;
private ProgressBar mSearchProgressBar;
private LinearLayout mViewsLl;
private ContactAdapter mFullContactAdapter = null;
private ArrayList<ListViewItem> mFullContactsArrayList = null;
public boolean isSoftKeyOn = false;
public boolean isPortrait;
private long mLastTimeTextChanged = 0L;
private long mCurrentTime = 0L;
private Filter mFilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts_list);
RelativeLayout windowRl = (RelativeLayout) findViewById(R.id.window_RelativeLayout);
LinearLayout progressBarLl = (LinearLayout) windowRl.findViewById(R.id.progressBar_LinearLayout);
mViewsLl = (LinearLayout) windowRl.findViewById(R.id.views_LinearLayout);
mSearchText = (EditText) mViewsLl.findViewById(R.id.contact_SearchEditText);
mSearchProgressBar = (ProgressBar) mViewsLl.findViewById(R.id.search_ProgressBar);
mLSListView = (LetterScrollListView) mViewsLl.findViewById(R.id.contacts_LetterScrollListView);
mLSListView.setSearchText(mSearchText);
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
isPortrait = true;
} else {
isPortrait = false;
}
final View activityRootView = windowRl;
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView()
.getHeight() - activityRootView.getHeight();
// if heightDiff > 100 pixels, its probably a keyboard...
if (heightDiff > 100) {
// Toast.makeText(getApplicationContext(), "Key ON",
// Toast.LENGTH_SHORT).show();
isSoftKeyOn = true;
} else {
// Toast.makeText(getApplicationContext(), "Key OFF",
// Toast.LENGTH_SHORT).show();
isSoftKeyOn = false;
mSearchText.clearFocus();
}
}
});
mSearchText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2,
int arg3) {
mCurrentTime = System.currentTimeMillis();
if( (mCurrentTime - mLastTimeTextChanged) <= USER_TYPE_DELAY ) {
mSearchInputHandler.removeMessages(WHAT_SEARCH);
}
// preparing message
Bundle bundle = new Bundle();
bundle.putCharSequence(USER_INPUT_KEY, cs);
Message message = mSearchInputHandler.obtainMessage(WHAT_SEARCH);
message.setData(bundle);
mSearchInputHandler.sendMessageDelayed(message, USER_TYPE_DELAY);
mLastTimeTextChanged = mCurrentTime;
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
// Create a progress bar to display while the list loads
mProgressBar = new ProgressBar(this);
mProgressBar.setIndeterminate(true);
progressBarLl.addView(mProgressBar);
getLoaderManager().initLoader(0, null, this).forceLoad();
}
#SuppressLint("HandlerLeak")
private final Handler mSearchInputHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
CharSequence cs = msg.getData().getCharSequence(USER_INPUT_KEY);
int what = msg.what;
switch(what) {
case WHAT_SEARCH:
// When user changed the Text after a delay
mSearchProgressBar.setVisibility(View.VISIBLE);
mFilter.filter(cs);
break;
}
}
};
public void removeSearchProgressBar() {
mSearchProgressBar.setVisibility(View.INVISIBLE);
}
/**
* Called when a new Loader needs to be created
*/
public Loader<ArrayList<ListViewItem>> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME
};
boolean showInvisible = false;
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
(showInvisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return new ContactArrayListLoader(this, uri, projection, selection, selectionArgs, sortOrder);
}
/**
* Called when a previously created loader has finished loading
*/
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {
mProgressBar.setVisibility(View.INVISIBLE);
if(mLSListView.getAdapter() == null) {
mFullContactsArrayList = data;
mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, mFullContactsArrayList);
mFilter = mFullContactAdapter.getFilter();
mLSListView.setAdapter(mFullContactAdapter);
}
}
/**
* Called when a previously created loader is reset, making the data unavailable
*/
public void onLoaderReset(Loader<ArrayList<ListViewItem>> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
//////mListView.setAdapter(new ContactAdapter(this, R.layout.contact_tuple, null));
mProgressBar.setVisibility(View.VISIBLE);
}
}
SOLVED
The problem is on the method
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {....}
On rotation/starting the app, the parameter data in this method is always the complete list and not the filtered list. So to get the filtered list on rotation, just create a static member
private static ArrayList<ListViewItem> sCurrentContactsArrayList = null;
and save before screen rotation like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if( TextUtils.isEmpty(mSearchText.getText()) ) {
sCurrentContactsArrayList = null;
} else {
sCurrentContactsArrayList = mFullContactAdapter.getCurrentItems();
}
}
also modify onLoadFinished():
public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {
mProgressBar.setVisibility(View.INVISIBLE);
if(mLSListView.getAdapter() == null) {
ArrayList<ListViewItem> contactsAL = null;
if(sCurrentContactsArrayList == null) {
contactsAL = data;
} else {
contactsAL = sCurrentContactsArrayList;
}
mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, contactsAL, data);
if(mFilter == null) mFilter = mFullContactAdapter.getFilter();
mLSListView.setAdapter(mFullContactAdapter);
}
mSearchText.setVisibility(View.VISIBLE);
}