Basically this is not a problem in itself, my code works so far.
What I have is a App, that lets a user log in and depending on his ID in the db, he gets displayed his saved notes. For this view I have this part of code:
title = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
MyDbHandler dbh = new MyDbHandler(this);
for(int i = 0; i < 999; i++) {
content = dbh.getNoteTitle(id, i); //getNoteTitle(int, int) returns String
if(content != null && content != "0")
title.add(content);
else
break;
}
list.setAdapter(title);
As I said, this works so far.
Thing is - I am very unhappy with the use of ' break; ' here, as I learned during education, this shouldn't be used.
Is there a smoother way to approach this issue?
Also ' content != "0" ' should be ' ! content.equals("0") ' normally, right? But that one doesn't work then... Why is this?
I am not sure what are you trying to do. First of all you should use "equal" method for Strings. The condition "content != "0" will always be true, because you are comparing 2 different objects. The condition "! content.equals("0")" should return true most of the time (when the value is not "0") and probably you should use the debugger to see exactly what is the value of content.
Second if you want to take all the notes from the database and show them to the user you should have first a method in the SQLiteOpenHelper similar to (it is not efficient to interrogate the database for each item, plus the separation of concerns):
public ArrayList<String> getNotesList (int userID){
SQLiteDatabase db = getWritableDatabase();
Cursor c = db.query(TABLE_NAME, new String[] {MyDbHandler.COLUMN_NOTE_TITLE}, MyDbHandler.userID + "=" + userID,null, null, null, null);
ArrayList<String> list = null;
String noteTitle;
if (c != null && c.moveToFirst())
{
list = new ArrayList<String>(c.getCount());
for (int i = 0; i < c.getCount(); i++)
{
noteTitle = c.getString(c.getColumnIndex(MyDbHandler.COLUMN_SESSION_PATH));
list.add(noteTitle);
c.moveToNext();
}
}
c.close();
db.close();
return list;
I think you should not save notes that you don't want to use (e.g. null or "0"), so instead of checking here, I would check in the addNote method.
For the list initialization you have:
MyDbHandler dbh = new MyDbHandler(this);
ArrayList listData = dbh.getNotesList(id)
if (listData != null && listData.length != 0){
title = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
listData.setAdapter(title);
}
I didn't test the code, but I hope it helps you. Good luck!
Related
I have 5 empty TextViews where I add the names. After adding a name, it is stored in a database. The database consist on 2 columns, the item ID and the item NAME. This is an example of what I'm doing:
- Mark1 //ID=1, NAME= Mark1
- Mark2 //ID=2, NAME= Mark2
- Mark3 //ID=3, NAME= Mark3
- Empty
- Empty
I add and edit perfectly the textViews, but I'm facing a problem when deleting. This has something to do with the way I'm getting the values from the database, I'll explain:
Every time the app starts, or I edit, add or delete one element, what I do is get the items from the database, get them into a Map, and copy them into the textviews (whose at a first time are invisible) making visible just the ones that have a name setted.
This is the code I use to do that:
public void getTravelers() {
/*Create map where store items*/
Map<Integer, String> nameList = new HashMap<Integer, String>();
/*Lon in providers query() method to get database's items and save them into the map*/
Cursor c = getContentResolver().query(TravelersProvider.CONTENT_URI, PROJECTION, null, null, null);
if (c.moveToFirst()) {
do {
nameList.put(Integer.parseInt(c.getString(c.getColumnIndex(Travelers._ID))), c.getString(c.getColumnIndex(Travelers.NAME)));
}while(c.moveToNext());
}
if (c != null && !c.isClosed()) {
c.close();
}
/*Check size*/
int size = nameList.size();
if (size >= 1) {
/*Save items in TextViews*/
//TODO: This is the code I should fix
for (int i = 0; i <= size; i++) {
if (i==1) {
traveler1.setText(nameList.get(i).toString());
traveler1.setVisibility(View.VISIBLE);
}
if (i==2) {
traveler2.setText(nameList.get(i).toString());
traveler2.setVisibility(View.VISIBLE);
}
if (i==3) {
traveler3.setText(nameList.get(i).toString());
traveler3.setVisibility(View.VISIBLE);
}
if (i==4) {
traveler4.setText(nameList.get(i).toString());
traveler4.setVisibility(View.VISIBLE);
}
if (i==5) {
traveler5.setText(nameList.get(i).toString());
traveler5.setVisibility(View.VISIBLE);
}
}
}
}
The problem comes in the for loop. Let's supposse that from the items named above, I want to delete Mark2 with ID=2, so then the size of the new Map would be 2, and it would enter to (i == 1) and (i == 2). But when entering to this last one, it would do traveler2.setText(nameList.get(2).toString()); and as seen, there is no element existing with the ID=2 because that is the one that I've deleted and it throws a NPE.
So my question is, what would be the right way to do this without facing this problem?
You should go for switch case other than for loop. Than code will not be in loop.
Finally I get what I need just changing the Key value of the Map that was the same as the ID of the database:
if (c.moveToFirst()) {
int key = 0;
do {
key++;
nameList.put(key, c.getString(c.getColumnIndex(Travelers.NAME)));
}while(c.moveToNext());
}
if (c != null && !c.isClosed()) {
c.close();
}
Basically this way I don't need to change nothing more as now the key value of the Map will match with the Textview position
I was able to be extracted the data that interest me in this way:
Cursor stipcursor = dataBase.rawQuery("SELECT (riepilogo) AS stip FROM "+DbHelper.RIEPILOGO+" WHERE MESI = 'Gennaio' and ANNI = "+anno+"", null);
int colIndexstip = stipcursor.getColumnIndex("stip");
if (colIndexstip == -1)
return;
else
stipcursor.moveToFirst();
double stip = stipcursor.getDouble(colIndexstip);
System.out.println("Riepilogo"+stip);
the problem is that if the database has data, everything works, but if the database is empty, the application crashes.
As given in this post, try this
if ( cursor.moveToFirst() ) {
// start activity a
} else {
// start activity b
}
cursor.moveToFirst() will return false if the cursor is empty. It works for me always.
You can try the first method given on that post also.
I have read several posts here on speed issues when looping through a cursor and tried the answers given in these posts such as e.g. do not use getcolumnindex in the loop call this once etc.
However with a database having around 2400 records it takes around 3 to 5 minutes to finish.
The loop is running in an async task method so that it does not hang up the device and the database is handled via a database adapter.
The loop code is as follows :
while (!exportrec.isAfterLast()) {
if ( exportrec.moveToNext() ) {
fulldate = exportnumberformatter(exportrec.getInt(daye))
+"/"+exportnumberformatter(exportrec.getInt(monthe))+"/"
+String.valueOf(exportrec.getInt(yeare));
fulltime = exportnumberformatter(exportrec.getInt(houre))+":"
+exportnumberformatter(exportrec.getInt(mine))+":"
+exportnumberformatter(exportrec.getInt(sece));
noiseid = exportrec.getInt(typee);
exportedinfo += exporttypes[id] +","+exportrec.getString(notee)+","+
fulldate+","+fulltime+" \n" ;
}
}
The exportnumberformatter does the following :
public String exportnumberformatter(int i) {
String result = Integer.toString(i);
if (result.length() >1 ) {
return Integer.toString(i);
}
String zeroprefix = "";
zeroprefix = "0"+result;
return zeroprefix ;
}
The cursor is called as follows before the loop to get the data :
exportrec = MD.GetAllLogs(2, "date_sort");
exportrec.moveToFirst();
The MD is the database adapter and the GetAllLogs Method (this has been played with to try and speed things up and so the date_sort that is used is really ignored here):
public Cursor GetAllLogs(Integer i,String sortfield)
{
String sorted = "";
if (i == 1 ) {
sorted = "DESC";
} else if (i == 2) {
sorted = "ASC";
}
return mDB.query(DB_TABLE, new String[] {COL_ID, COL_TYPE,COL_IMAGE, COL_INFO,COL_IMAGE,COL_HOUR,COL_SEC,COL_MIN,COL_DAY,COL_MON,COL_YEAR,COL_SORT_DATE},
null, null, null, null, COL_ID+" "+sorted);
}
When I created the table in the database it had no indexes so I created these via the upgrade method. However they did not error or appear to fail when I did this but what I do not know is A) does the database/table need rebuilding after an index is created and B) how to tell if they have been created ? the two indexes were based on the ID as the first and a field that holds the year month day hour minute second all in on Long Integer.
I am concerned that the loop appears to be taking this long to read through that many records.
Update:
rtsai2000's and the suggestion from CL answer has improved the speed from minutes to seconds
Your exportedInfo String is growing and growing. Save the results in an array and Stringify later (such as with StringBuilder).
You are not closing your cursor after reading the records.
List<String> exportedInfo = new ArrayList<String>();
Cursor exportrec = GetAllLogs();
try {
while (exportrec.moveToNext()) {
String info = String.format("%s, %s, %02d/%02d/%02d, %02d:%02d:%02d",
exporttypes[id],
exportrec.getString(notee),
exportrec.getInt(daye),
exportrec.getInt(monthe),
exportrec.getInt(yeare),
exportrec.getInt(houre),
exportrec.getInt(mine),
exportrec.getInt(sece));
exportedInfo.add(info);
}
} finally {
exportrec.close();
}
return exportedInfo;
I'm trying to save user information in my application. I have Employee number editText and Company EditText. My employee number is not a required field so that means my table can have null values. My problem is when I am comparing if the employee number entered by the user already exist in my database, it also reads the null values when the user do not enter anything on the employee number editText. Can anyone help me do this please?
This is my code where I save all the employee number in an arraylist and remove all the null values
ArrayList<String> employeenumber = databaseAdapter.getEmployeeNumber();
employeenumber.removeAll(Collections.singleton(null));
employeenumber.removeAll(Collections.singleton(""));
What I wanna do is, if the user enter employee number, it will check if the arraylist contains it and if yes, it will all check the company corresponds to it. I need to trap duplicate entry. For example the employee number is 1234 and the company is ABCD, the program must not accept it. Thanks for anyone who could help me.
First check whether the user enter something on employee number editText. Then use int flag to compare it. Try the code below in your main activity:
int flag1 = 0;
if (!Emp.equals(""))
{
ArrayList<String> CompanyandEmp = new ArrayList<String>();
CompanyandEmp = databaseAdapter.getCompanyEmp(Emp);
CompanyandEmp.removeAll(Collections.singleton(""));
for(int i=0;i< CompanyandEmp.size();i++)
{
String cmpemp = CompanyandEmp.get(i).toString();
if(cmpemp.equalsIgnoreCase(companyName))
{
flag1 = 1;
}
}
}
if (flag1 == 0)
{
//as per your requirement
}else{
Toast.makeText(RegistrationActivity.this, "Account info already exist.", Toast.LENGTH_LONG).show();
}
Then in your databaseAdapter:
public ArrayList<String> getCompanyEmp(String emp) {
SQLiteDatabase db = this.getReadableDatabase();
ArrayList<String> companyemp = new ArrayList<String>();
try {
Cursor c = db.query("select CompName FROM projsitemast where Emp='"+emp+"'", null);
if (c != null) {
c.moveToFirst();
for (int j = 0; j < c.getCount(); j++) {
companyemp.add(c.getString(0));
c.moveToNext();
}
c.close();
}
return companyemp;
} catch (Exception e) {
e.printStackTrace();
}
return companyemp;
}
I am working on android project and am making using of a ListView that retrieves data from the SQLite database.
I am making a dataset using an ArrayList and then adding this ArrayList into an ArrayAdapter.
When the data is being retrieved from the database, I am telling SQLite to do the sorting so everything is in alphabetical order when it is added into the ListView. At certain times, the information will be added dynamically to to the ListView without it requiring to re-fetch everythin from the database again. However, I want to keep everything in alphabetical order.
How would I do this, do I sort the DataSet and then call the notifyDataSet Changes or do I do the sort directly on the ArrayAdapter. I've looked into performing the sort on the ArrayAdapter but this wants an argument that uses a Comparator but not sure what this is and can't find any working examples that may be of any help for what I want to achieve.
Below is the code that populates the array and sets the list adapter
ArrayList<Spanned> passwords = managePasswordList.getPasswordList();
if (passwords != null && passwords.size() > 0)
{
passwordArrayAdapter = new ArrayAdapter<Spanned>(getActivity().getApplicationContext(),
android.R.layout.simple_list_item_activated_1, passwords);
setListAdapter(passwordArrayAdapter);
myListView.setTextFilterEnabled(true);
txtNoRecords.setVisibility(View.GONE);
}
else
{
txtNoRecords.setVisibility(View.VISIBLE);
}
I am then adding data to the dataset and refreshing the list view using the following
String company = Encryption.decrypt(passwords.get(i).company);
String username = Encryption.decrypt(passwords.get(i).username);
details = Html.fromHtml(company + "<br />" + "<small><font color=\"#767676\">" + username + "</b></small>");
passwords.add(details);
passwordArrayAdapter.notifyDataSetChanged();
Thanks for any help you can provide.
UPDATE 1
I've tried doing what Nick Bradbury suggested but I am having a problem with the comparator. I have the following code but I don't know where to go from here.
SQLiteDatabase myDb = null;
Cursor cursor = null;
ArrayList<Spanned> passwords = new ArrayList<Spanned>();
try
{
myDb = context.openOrCreateDatabase("PasswordManager", Context.MODE_PRIVATE, null);
cursor = myDb.rawQuery("SELECT * FROM password ASC", null);
while (cursor.moveToNext())
{
final String company = Encryption.decrypt(cursor.getString(2));
final String username = Encryption.decrypt(cursor.getString(4));
Spanned details = Html.fromHtml(company + "<br />" + "<small><font color=\"#767676\">" + username + "</b></small>");
passwords.add(details);
Collections.sort(passwords, new Comparator<Spanned>() {
public int compare(Spanned lhs, Spanned rhs) {
return 0;
}
});
}
}
catch (SQLiteException ex)
{
common.showBasicAlertDialog("Unfortunately something has gone wrong.\n\nWe will fix this as soon as we can", false);
Log.e("Database Error", ex.toString());
return null;
}
In the return statement I have no idea what to do, I've tried return lhs.compareTo but the lhs and rhs variables don't have the compareTo function so I have not got a clue what to do.
Here's a simple example of sorting an ArrayList using Comparator. In this example, the ArrayList is defined as:
public class StatusList extends ArrayList<Status>
A sort routine for this ArrayList could look like this:
public void sort() {
Collections.sort(this, new Comparator<Status>() {
#Override
public int compare(Status item1, Status item2) {
return item2.getDate().compareTo(item1.getDate());
}
});
}
Replace <Status> with whatever object your ArrayList contains, then change the comparison to compare the values of the object you wish to sort by.