Android set new Cursor to a listView - android

I have a little issue with settings a new Adapter to a listView when user enter letters in EditText. So the thing which I'm doing is, when my Activity starts for the first time, I'm populating the listView from Database with Cursor and Custom Adapter. When user enter some text in EditText I'm creating new sql statement and getting the data with new Cursor. After that I'm creating new Custom Adapter and trying to set it to my list view.
The problem is that when I start typing in edit text I can saw in Logs from LogCat that the sql statement is the right one, and cursor size, but my ListView isn't populated with the new data. It's staying the same. Here is how I'm doing it :
This is how I'm populating the listView for first time :
cursor = userDbHelper.executeSQLQuery(sqlQuery);
if (cursor.getCount() == 0) {
noCards.setVisibility(View.VISIBLE);
noCards.setText(getString(R.string.no_cards));
} else if (cursor.getCount() > 0) {
noCards.setVisibility(View.GONE);
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
objectId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
cardId.add(objectId);
title = cursor.getString(cursor.getColumnIndex("title"));
catTitle = cursor.getString(cursor.getColumnIndex("catTitle"));
int repeats = Integer.parseInt(cursor.getString(cursor.getColumnIndex("repeatsCount")));
count.add(repeats);
if(extra != 0){
String cardsm = "SELECT objectId FROM cardmedias "
+ "WHERE cardId="
+ objectId
+ " AND mediaType="
+ 5012;
Cursor cardsM = userDbHelper.executeSQLQuery(cardsm);
if (cardsM.getCount() == 0) {
} else if (cardsM.getCount() > 0) {
for (cardsM.move(0); cardsM.moveToNext(); cardsM.isAfterLast()) {
objectID = Integer.parseInt(cardsM.getString(cardsM.getColumnIndex("objectId")));
String filename = "mediacard-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, this);
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
Log.i("","path : "+path);
paths.add(path);
names.add(title);
categories.add(catTitle);
}
}
} else if (extra==0){
names.add(title);
categories.add(catTitle);
}
}
}
cursor.close();
adapter = new LazyAdapter(this, paths, names, categories, count);
listView.setAdapter(adapter);
and this is how I'm creating the new Cursor and adapter with TextWatcher :
searchString = "";
sqlQuery = getSqlQuery(sort, collId, ascDesc,searchString);
searchBar.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
check = 1;
listView.setAdapter(null);
searchString = s.toString();
Log.e("","searchString : "+searchString);
sqlQuery = getSqlQuery(sort, collId, ascDesc,searchString);
Log.e(""," sqlquery : "+sqlQuery);
Cursor cursor = userDbHelper.executeSQLQuery(sqlQuery);
Log.e("","cursor count : "+cursor.getCount());
if (cursor.getCount() == 0) {
noCards.setVisibility(View.VISIBLE);
noCards.setText(getString(R.string.no_cards));
} else if (cursor.getCount() > 0) {
noCards.setVisibility(View.GONE);
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
objectId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
cardId.add(objectId);
title = cursor.getString(cursor.getColumnIndex("title"));
catTitle = cursor.getString(cursor.getColumnIndex("catTitle"));
int repeats = Integer.parseInt(cursor.getString(cursor.getColumnIndex("repeatsCount")));
count.add(repeats);
if(extra != 0){
String cardsm = "SELECT objectId FROM cardmedias "
+ "WHERE cardId="
+ objectId
+ " AND mediaType="
+ 5012;
Cursor cardsM = userDbHelper.executeSQLQuery(cardsm);
if (cardsM.getCount() == 0) {
} else if (cardsM.getCount() > 0) {
for (cardsM.move(0); cardsM.moveToNext(); cardsM.isAfterLast()) {
objectID = Integer.parseInt(cardsM.getString(cardsM.getColumnIndex("objectId")));
String filename = "mediacard-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, OwnedStampii.this);
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
Log.i("","path : "+path);
paths.add(path);
names.add(title);
categories.add(catTitle);
}
}
} else if (extra==0){
names.add(title);
categories.add(catTitle);
}
}
}
cursor.close();
LazyAdapter adapter = new LazyAdapter(OwnedStampii.this, paths, names, categories, count);
listView.setAdapter(adapter);
}
});
So any ideas how can I refresh my list View with the new adapter. I've already tried with adapter.notifySetDataChanged(); and it's not working.
Thanks in advance!

clear your data sources in this case it is paths, names, categories, count.
Load new results into data sources of list(paths, names, categories, count), and don's set list adapter to null, and call notifyDataSetChanged.

I fix that, in my afterTextChanged() I'm just clearing the arraylists using for storing the data and putting the new data on them.

Related

How I can use substring in cursor?

I have a Cursor that Select from sqlite, in this query I do a substring but I can'y use from substring it don't get me any error but show me listView empty.
try {
String value = editText.getText().toString();
cursor = sql.rawQuery(
"SELECT MetaDataID,Data,CategoryID,ParentID FROM Book WHERE Data LIKE '"
+ "%" + value + "%'", null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
Struct_Search note = new Struct_Search();
note.MetaData = cursor.getInt(cursor.getColumnIndex("MetaDataID"));
Result = cursor.getString(cursor.getColumnIndex("Data"));
int A = Result.indexOf(value);
String V = Result.substring(A,100);
note.Value = V;
note.NumberAyeh = cursor.getInt(cursor.getColumnIndex("CategoryID"));
ParentID = cursor.getInt(cursor.getColumnIndex("ParentID"));
CursorSecond = sql.rawQuery("SELECT name FROM ContentList WHERE id ="+ ParentID, null);
if (CursorSecond != null) {
do {
CursorSecond.moveToFirst();
note.NameSureh = CursorSecond.getString(CursorSecond.getColumnIndex("name"));
CursorSecond.close();
} while (CursorSecond.moveToNext());
}
notes.add(note);
} while (cursor.moveToNext());
}
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
} finally {
cursor.close();
}
Notice : This line don't work :
String V = Result.substring(A,100);
note.Value = V;
If you are trying to get the FIRST 100 characters AFTER index of character, and set note.Value to it, change your substring to be
// substring(int beginIndex, int endIndex)
Result.substring(A, A + 100);
In java, the second parameter of substring is endIndex, not Length.

Android: How to Extract the data in 1 row with 2 columns

Here are my codes for my Search Activity
search.addTextChangedListener(new TextWatcher()
{
public void afterTextChanged(Editable s)
{
// Abstract Method of TextWatcher Interface.
}
public void beforeTextChanged(CharSequence s,
int start, int count, int after)
{
// Abstract Method of TextWatcher Interface.
}
public void onTextChanged(CharSequence s,
int start, int before, int count)
{
textlength = search.getText().length();
array_sort.clear();
for (int i = 0; i < listview_array.length; i++)
{
if (textlength <= listview_array[i].length())
{
if(search.getText().toString().equalsIgnoreCase(
(String)
listview_array[i].subSequence(0,
textlength)))
{
array_sort.add(listview_array[i]);
}
}}
listContent1.setAdapter(new ArrayAdapter<String>
(Search_Food.this,
android.R.layout.simple_list_item_1, array_sort));
}
});
my onclicklistener code
AlertDialog.Builder adb = new AlertDialog.Builder(
Search_Food.this);
adb.setTitle("Food Item");
adb.setMessage("Selected Food is = "
+ listContent1.getItemAtPosition(position));
adb.setPositiveButton("Ok", null);
adb.show();
my Dbadapter
public LinkedList<String> search(String string) {
// TODO Auto-generated method stub
LinkedList<String> results = new LinkedList<String>();
Cursor cursor = null;
String search = string;
try{
cursor = this.sqLiteDatabase.query(true, MYDATABASE_TABLE , new String[] { KEY_ID , KEY_FOODNAME , KEY_CALORIES }, KEY_FOODNAME + " = ?" + "COLLATE NOCASE",
new String[] { search }, null, null, null, null);
if(cursor!=null && cursor.getCount()>0 && cursor.moveToFirst()){
int foodName = cursor.getColumnIndex(KEY_FOODNAME );
int keyColories = cursor.getColumnIndex(KEY_CALORIES );
// boolean moveToNext = cursor.moveToNext();
//do{
results.add(
new String(
cursor.getString(foodName) + " " +
cursor.getString(keyColories)
)
);
//}while(moveToNext);
}
}catch(Exception e){
Log.e(APP_NAME, "An error occurred while searching for "+search+": "+e.toString(), e);
}finally{
if(cursor!=null && !cursor.isClosed()){
cursor.close();
}
}
return results;
}
now when i click a data on my searched listview, i want to extract the getitemposition into 2 and thats my columns. the food name and the calories. how can i separate the 2 values.
answers please. help. thank you

Android - Loading the same intent with different data

I'm loading the same page with different data. I've got it so it's listing my items and when I click one, it's sending the correct next page type and ID through. But it's still loading my first pages SQLStatement. The right things are being logged out.
Do I need to clear it down or something first?
Here is my code:
public class LocationListView extends Activity {
String SQLStatement;
String itemID = "1001-0001021";
String Type;
;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_list_view);
Bundle extras = getIntent().getExtras();
String dataType;
String dataID;
if (extras != null) {
dataType = extras.getString("Type");
dataID = extras.getString("ID");
} else {
dataType = "notset";
dataID = "notset";
}
File dbfile = new File(Global.currentDBfull);
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile, null);
if(dataType == "notset") {
SQLStatement = "select * from stationobjects where stationid= " + Global.StationID + " and objectid=0";
Type = "Room";
} else if(dataType == "Room") {
SQLStatement = "select * from stationobjects where stationid= " + Global.StationID + " and objectid=1001 and diagramid like '"+ itemID +"%'";
Type = "Area";
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} else if(dataType == "Area") {
Type = "Zone";
} else if(dataType == "Zone") {
} else {
SQLStatement = "select * from stationobjects where stationid= " + Global.StationID + " and objectid=0";
Type = "Room";
}
Cursor c = db.rawQuery(SQLStatement, null);
if(c.getCount() != 0) {
Log.e("LocationListView", "Found Items");
c.moveToFirst();
ArrayList<String> mItemName = new ArrayList<String>();
final ArrayList<String> mItemID = new ArrayList<String>();
c.moveToFirst();
while(!c.isAfterLast()) {
mItemName.add(c.getString(c.getColumnIndex("Name")));
mItemID.add(c.getString(c.getColumnIndex("StationObjectID")));
c.moveToNext();
}
final ListView listView = (ListView) findViewById(R.id.lvLocation);
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, mItemName);
int[] colors = {0, 0xFFFF0000, 0};
listView.setDivider(new GradientDrawable(Orientation.RIGHT_LEFT, colors));
listView.setDividerHeight(1);
listView.setAdapter(adapter);
listView.setClickable(true);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Object o = listView.getItemAtPosition(position);
String StationObjectID = mItemID.get(position);
Log.e("LocationListView", "" + o);
Log.e("LocationListView", "" + StationObjectID);
startActivityForResult(SwapPage, 0);
}
});
} else {
Log.e("LocationListView", "Not Found Items");
Context context = getApplicationContext();
CharSequence text = "Sorry No data returned";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
db.close();
}
}
The data from your Intent looks correct, the problem is that in Java you must compare Strings like this:
if(dataType.equals("notset"))
not:
if(dataType == "notset")
Detailed explanation: How do I compare strings in Java?

How load all the contacts with minimum time in Android

In my project getting contacts is taking a long time to load.
What are ways to reduce the time of getting contacts
Assume there are 1000 contacts in my phone.
Right now it is taking more than 2 minutes to load all the contacts
How can I reduce the time to load contacts ?
Any Thoughts?
I referred to the the following link when programming the initial method.
http://www.coderzheaven.com/2011/06/13/get-all-details-from-contacts-in-android/
BETTER SOLUTION HERE.....
private static final String[] PROJECTION = new String[] {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER
};
.
.
.
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
if (cursor != null) {
try {
final int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String name, number;
while (cursor.moveToNext()) {
name = cursor.getString(nameIndex);
number = cursor.getString(numberIndex);
}
} finally {
cursor.close();
}
}
CHEERS...:)
Total time will depend upon what fields you are trying to access from the Contacts table.
Accessing less field means less looping , less processing and hence faster results.
Also to speed up your contacts fetch operation you can use the ContentProvideClient instead of calling query on ContentResolver every time. This will make you query the specific table rather than querying first for the required ContentProvider and then to table.
Create an instance of ContentProviderClient
ContentResolver cResolver=context.getContextResolver();
ContentProviderClient mCProviderClient = cResolver.acquireContentProviderClient(ContactsContract.Contacts.CONTENT_URI);
Then reuse this mCProviderClient to get Contacts(data from any ContentProvider) data on your call.
For example in following method, I am accessing only one field.
private ArrayList<String> fetchContactsCProviderClient()
{
ArrayList<String> mContactList = null;
try
{
Cursor mCursor = mCProviderClient.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (mCursor != null && mCursor.getCount() > 0)
{
mContactList = new ArrayList<String>();
mCursor.moveToFirst();
while (!mCursor.isLast())
{
String displayName = mCursor.getString(mCursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
mContactList.add(displayName);
mCursor.moveToNext();
}
if (mCursor.isLast())
{
String displayName = mCursor.getString(mCursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
mContactList.add(displayName);
}
}
mCursor.close();
}
catch (RemoteException e)
{
e.printStackTrace();
mContactList = null;
}
catch (Exception e)
{
e.printStackTrace();
mContactList = null;
}
return mContactList;
}
Load Contact faster like other apps doing.
I have tested this code with multiple contacts its working fine and faster like other apps within 500 ms (within half second or less) I am able to load 1000+ contacts.
Total time will depend upon what fields you are trying to access from the Contacts table.
Mange your query according to your requirement do not access unwanted fields. Accessing less field means less looping , less processing and hence faster results.
Accessing right table in contact it also help to reduce contact loading time.
Query Optimization to load contact more faster use projection
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI,
ContactsContract.Contacts.STARRED,
ContactsContract.RawContacts.ACCOUNT_TYPE,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE
};
Selection and selection argument
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)" + " AND " /*+ ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + 1 + "' AND "*/ +
ContactsContract.Data.HAS_PHONE_NUMBER + " = '" + 1 + "'";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
To order contacts alphabetically use following code
try {
Collections.sort(listview_address, new Comparator<ContactBook>() {
#Override
public int compare(ContactBook lhs, ContactBook rhs) {
return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
}
});
} catch (Exception e) {
e.printStackTrace();
}
Following is complete source code
public void initeContacts() {
List<ContactBook> listview_address = new LinkedList<ContactBook>();
SparseArray<ContactBook> addressbook_array = null;
{
addressbook_array = new SparseArray<ContactBook>();
long start = System.currentTimeMillis();
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI,
ContactsContract.Contacts.STARRED,
ContactsContract.RawContacts.ACCOUNT_TYPE,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)" + " AND " /*+ ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" + 1 + "' AND "*/ +
ContactsContract.Data.HAS_PHONE_NUMBER + " = '" + 1 + "'";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Uri uri = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
} else {
uri = ContactsContract.Data.CONTENT_URI;
}
// we could also use Uri uri = ContactsContract.Data.CONTENT_URI;
// we could also use Uri uri = ContactsContract.Contact.CONTENT_URI;
Cursor cursor = getActivity().getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
final int photo = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.PHOTO_URI);
final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);
final int account_type = cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_TYPE);
while (cursor.moveToNext()) {
int contact_id = cursor.getInt(idIdx);
String photo_uri = cursor.getString(photo);
String contact_name = cursor.getString(nameIdx);
String contact_acc_type = cursor.getString(account_type);
int contact_type = cursor.getInt(typeIdx);
String contact_data = cursor.getString(dataIdx);
ContactBook contactBook = addressbook_array.get(contact_id);
/* if (contactBook == null) {
//list contact add to avoid duplication
//load All contacts fro device
//to add contacts number with name add one extra veriable in ContactBook as number and pass contact_data this give number to you (contact_data is PHONE NUMBER)
contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "phone number");
addressbook_array.put(contact_id, contactBook);
listview_address.add(contactBook);
}*/
String Contact_mimeType = cursor.getString(mimeTypeIdx);
//here am checking Contact_mimeType to get mobile number asociated with perticular contact and email adderess asociated
if (Contact_mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
if (contactBook != null) {
contactBook.addEmail(contact_type, contact_data);
}
} else {
if (contactBook == null) {
//list contact add to avoid duplication
//load All contacts fro device
//to add contacts number with name add one extra veriable in ContactBook as number and pass contact_data this give number to you (contact_data is PHONE NUMBER)
contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "phone number");
addressbook_array.put(contact_id, contactBook);
listview_address.add(contactBook);
}
// contactBook.addPhone(contact_type, contact_data);
}
}
cursor.close();
try {
Collections.sort(listview_address, new Comparator<ContactBook>() {
#Override
public int compare(ContactBook lhs, ContactBook rhs) {
return lhs.name.toUpperCase().compareTo(rhs.name.toUpperCase());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
You can use following code in above code that I have commented .It club the the single contact with its multiple number.To get all number associated with single contact use array in Object class.
if (contactBook == null) {
//irst contact add to avoid duplication
//load All contacts fro device
contactBook = new ContactBook(contact_id, contact_name, getResources(), photo_uri, contact_acc_type, "");
addressbook_array.put(contact_id, contactBook);
listview_address.add(contactBook);
}
String Contact_mimeType = cursor.getString(mimeTypeIdx);
//here am checking Contact_mimeType to get mobile number asociated with perticular contact and email adderess asociated
if (Contact_mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
contactBook.addEmail(contact_type, contact_data);
} else {
contactBook.addPhone(contact_type, contact_data);
}
Object class
public class ContactBook {
public int id;
public Resources res;
public String name;
public String photo;
public String contact_acc_type;
public SparseArray<String> emails;
public SparseArray<String> phones;
/* public LongSparseArray<String> emails;
public LongSparseArray<String> phones;*/
public String header = "";
public ContactBook(int id, String name, Resources res, String photo, String contact_acc_type, String header) {
this.id = id;
this.name = name;
this.res = res;
this.photo = photo;
this.contact_acc_type = contact_acc_type;
this.header = header;
}
#Override
public String toString() {
return toString(false);
}
public String toString(boolean rich) {
//testing method to check ddata
SpannableStringBuilder builder = new SpannableStringBuilder();
if (rich) {
builder.append("id: ").append(Long.toString(id))
.append(", name: ").append("\u001b[1m").append(name).append("\u001b[0m");
} else {
builder.append(name);
}
if (phones != null) {
builder.append("\n\tphones: ");
for (int i = 0; i < phones.size(); i++) {
int type = (int) phones.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, ""))
.append(": ")
.append(phones.valueAt(i));
if (i + 1 < phones.size()) {
builder.append(", ");
}
}
}
if (emails != null) {
builder.append("\n\temails: ");
for (int i = 0; i < emails.size(); i++) {
int type = (int) emails.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, ""))
.append(": ")
.append(emails.valueAt(i));
if (i + 1 < emails.size()) {
builder.append(", ");
}
}
}
return builder.toString();
}
public void addEmail(int type, String address) {
//this is the array in object class where i am storing contact all emails of perticular contact (single)
if (emails == null) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
emails = new SparseArray<String>();
emails.put(type, address);
/*} else {
//add emails to array below Jelly bean //use single array list
}*/
}
}
public void addPhone(int type, String number) {
//this is the array in object class where i am storing contact numbers of perticular contact
if (phones == null) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
phones = new SparseArray<String>();
phones.put(type, number);
/* } else {
//add emails to array below Jelly bean //use single array list
}*/
}
}}
For loading the contacts with mininum time the optimum solution is to use the concept of projection and selection argument while querying the cursor for contacts.
this can be done in following way
void getAllContacts() {
long startnow;
long endnow;
startnow = android.os.SystemClock.uptimeMillis();
ArrayList arrContacts = new ArrayList();
Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Cursor cursor = ctx.getContentResolver().query(uri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.Contacts._ID}, selection, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
cursor.moveToFirst();
while (cursor.isAfterLast() == false) {
String contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
int phoneContactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
int contactID = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID));
Log.d("con ", "name " + contactName + " " + " PhoeContactID " + phoneContactID + " ContactID " + contactID)
cursor.moveToNext();
}
cursor.close();
cursor = null;
endnow = android.os.SystemClock.uptimeMillis();
Log.d("END", "TimeForContacts " + (endnow - startnow) + " ms");
}
With above method it took 400ms(less than second) to load contacts where as in normall way it was taking 10-12 sec.
For details imformation this post might help as i took help from it
http://www.blazin.in/2016/02/loading-contacts-fast-from-android.html
If your time increases with your data, then you are probably running a new query to fetch phones/emails for every contact. If you query for the phone/email field using ContactsContract.CommonDataKinds.Phone.NUMBER, then you will just retrieve 1 phone per contact.
The solution is to project the fields and join them by contact id.
Here is my solution in Kotlin (extracting id, name, all phones and emails):
val projection = arrayOf(
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Contactables.DATA
)
val selection = "${ContactsContract.Data.MIMETYPE} in (?, ?)"
val selectionArgs = arrayOf(
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
val contacts = applicationContext
.contentResolver
.query(ContactsContract.Data.CONTENT_URI, projection, selection, selectionArgs, null)
.run {
if (this == null) {
throw IllegalStateException("Cursor null")
}
val contactsById = mutableMapOf<String, LocalContact>()
val mimeTypeField = getColumnIndex(ContactsContract.Data.MIMETYPE)
val idField = getColumnIndex(ContactsContract.Data.CONTACT_ID)
val nameField = getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
val dataField = getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA)
while (moveToNext()) {
val mimeType = getString(mimeTypeField)
val id = getString(idField)
var contact = contactsById[id]
if (contact == null) {
val name = getString(nameField)
contact = LocalContact(id = id, fullName = name, phoneNumbers = listOf(), emailAddresses = listOf())
}
val data = getString(dataField)
when(getString(mimeTypeField)) {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE ->
contact = contact.copy(emailAddresses = contact.emailAddresses + data)
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ->
contact = contact.copy(phoneNumbers = contact.phoneNumbers + data)
}
contactsById[id] = contact
}
close()
contactsById.values.toList()
}
And for reference, my LocalContact model:
data class LocalContact(
val id: String,
val fullName: String?,
val phoneNumbers: List<String>,
val emailAddresses: List<String>
)
I think this is a better solution:
public ContentValues getAllContacts() {
ContentValues contacts = new ContentValues();
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur != null && cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null);
if (pCur != null) {
while (pCur.moveToNext()) {
String phoneNo = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contacts.put(phoneNo, name);
}
pCur.close();
}
}
}
cur.close();
}
return contacts;
}
for use it you need to call this lines once:
ContentValues contacts = new ContentValues();
contacts = getAllContacts();
and when you want to get contact name by number, just use:
String number = "12345";
String name = (String) G.contacts.get(number);
this algorithm is a bit faster...

How to implement TextWatcher for SearchDialog

I need to update my ListView according to the userinput in SearchDialog. For this I need to set a TextWatcher for SearchDialog. How to do this?
you can do it as below:
yourEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// process new items for list view
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// push new items into adapter and call notifyDataSetChanged() on it
}
});
Here is what I did actually a few months ago to achieve the same thing that you need. I had to sort my list view depending on user input while I was populating the list view from sqlite database with sqlite statements. Not sure if it's the best way,but in my situation it works perfectly.
So on my EditText field I add this (which name is searchBar) :
searchString = "";
searchBar.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
// this is where actually I was changing the sqlite statement which sort my list view
names.clear();
categories.clear();
paths.clear();
count.clear();
cardId.clear();
myCardID.clear();
searchString = s.toString();
Log.e("","searchString : "+searchString);
sqlQuery = getSqlStatement(sort, collId, ascDesc,searchString);
Log.e(""," sqlquery : "+sqlQuery);
sqlQuery = getSqlStatement(sort, collId, ascDesc, searchString);
Cursor cursor = userDbHelper.executeSQLQuery(sqlQuery);
if (cursor.getCount() == 0) {
noCards.setVisibility(View.VISIBLE);
} else if (cursor.getCount() > 0) {
noCards.setVisibility(View.GONE);
for (cursor.move(0); cursor.moveToNext(); cursor.isAfterLast()) {
objectId = Integer.parseInt(cursor.getString(cursor.getColumnIndex("objectId")));
cardId.add(objectId);
title = cursor.getString(cursor.getColumnIndex("title"));
catTitle = cursor.getString(cursor.getColumnIndex("catTitle"));
if(extra!=0 && sort!=3){
tags.setText(catTitle);
}
int repeats = Integer.parseInt(cursor.getString(cursor.getColumnIndex("repeatsCount")));
count.add(repeats);
String cardsm = "SELECT objectId FROM cardmedias " +
"WHERE cardId="+
objectId +
" AND mediaType=" +
5012;
Cursor cardsM = userDbHelper.executeSQLQuery(cardsm);
if (cardsM.getCount() == 0) {
String defCard = "SELECT objectId FROM collectionmedias " +
"WHERE collectionId="+
collId +
" AND mediaType=" +
3003;
Cursor getDefCard = userDbHelper.executeSQLQuery(defCard);
getDefCard.moveToFirst();
objectID = Integer.parseInt(getDefCard.getString(getDefCard
.getColumnIndex("objectId")));
String filename = "mediacollection-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, getApplicationContext());
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
paths.add(path);
names.add(title);
categories.add(catTitle);
} else if (cardsM.getCount() > 0) {
for (cardsM.move(0); cardsM.moveToNext(); cardsM.isAfterLast()) {
objectID = Integer.parseInt(cardsM.getString(cardsM
.getColumnIndex("objectId")));
String filename = "mediacard-"+objectID;
if(storageID==1){
path = RPCCommunicator.getImagePathFromInternalStorage(servername, userId, filename, getApplicationContext());
} else if(storageID==2){
path = RPCCommunicator.getImagePathFromExternalStorage(servername, userId, filename);
}
hm.put(objectID, path);
path = hm.get(objectID);
paths.add(path);
names.add(title);
categories.add(catTitle);
}
}
cardsM.close();
}
}
cursor.close();
// don't forget to add this!!!
adapter.notifyDataSetChanged();
}
});
And in my onCreate() actually I'm doing the same thing as in TextWatcher to sort my list view, so I think you can implement the same logic as I did.
If you have any problems to do that, just paste some of your code so we can help you! : )
Hope this helps!

Categories

Resources