lundi 9 mars 2015

Android: Getting search results from sqlite data base

I have been following this tutorial to try and implement a searchview. Which will get results from a sqlite database and return them in a listview. The database will be populated by an xml file which will be parsed. However, I am receiving errors regarding: attempt to re-open an already-closed object: SQLiteDatabase:


Also i am unsure how to adapt the namelist in the tutorial to what I want.


SearchActivity



public class SearchActivity extends Activity implements SearchView.OnQueryTextListener,
SearchView.OnCloseListener {

private SearchView searchView; //my searchview widget
private ListView myList; // my listview widget
private BooksDBAdapter mDbHelper; //my database
@SuppressWarnings("rawtypes")
private ArrayList<Books> nameList; //my arraylist of books
private MyAdapter defaultAdapter; //my adapter to put the information into list

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);

ArrayList nameList = new ArrayList();
//relate listView from java to the created xml
myList = (ListView) findViewById(R.id.listView);
//show list
defaultAdapter = new MyAdapter(SearchActivity.this, nameList);
myList.setAdapter(defaultAdapter);

//set searchview
searchView = (SearchView) findViewById(R.id.searchView);
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(this);//listens to queries
searchView.setOnCloseListener(this);

//create new instance of db
mDbHelper = new BooksDBAdapter(this);
mDbHelper.open();

//Clear all names
// mDbHelper.deleteAllBooks();

//get internal xmlfile to parse
XmlResourceParser xpp = getResources().getXml(R.xml.books);

try {
// mDbHelper = new BooksDBAdapter(this);
// mDbHelper.open();

// get initial eventType

while (xpp.next() != XmlPullParser.END_TAG) {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = xpp.getName();

if (name.equals("book")) {
String author = null, title = null, genre = null, price = null, publish_date = null, description = null;
while (xpp.next() != XmlPullParser.END_TAG) {
if (xpp.getEventType() != XmlPullParser.START_TAG) {
continue;
}
name = xpp.getName();
switch (name) {
case "author":
author = readText(xpp);
break;
case "title":
title = readText(xpp);
break;
case "genre":
genre = readText(xpp);
break;
case "price":
price = readText(xpp);
break;
case "publish_date":
publish_date = readText(xpp);
break;
case "description":
description = readText(xpp);
break;
}
}
mDbHelper.createBooks(author, title, genre, price, publish_date, description);
//do the create books method in db class, to create table of books
}
}
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
} finally {
if (mDbHelper != null && mDbHelper == mDbHelper.open()) {
mDbHelper.close();
}

}


}

//method to read the xml text
private String readText(XmlPullParser xpp) throws IOException,
XmlPullParserException {
String result = "";
if (xpp.next() == XmlPullParser.TEXT) {
result = xpp.getText();
xpp.nextTag();
}
return result;
}

@Override
protected void onDestroy() {
super.onDestroy();

if (mDbHelper != null && mDbHelper == mDbHelper.open()) {
mDbHelper.close();
}
}


@Override
public boolean onClose() {
myList.setAdapter(defaultAdapter);
return false;
}


@Override
public boolean onQueryTextChange(String newText) {
if (!newText.isEmpty()) {
displayResults(newText + "*");
} else {
myList.setAdapter(defaultAdapter);
}
return false;
}

@Override
public boolean onQueryTextSubmit(String query) {
displayResults(query + "*");
return false;
}

//search and results method
private void displayResults(String query) {

Cursor cursor = mDbHelper.searchBooks((query != null ? query : "@@@@"));

if (cursor != null) {

String[] from = new String[]{
BooksDBAdapter.KEY_AUTHOR,
BooksDBAdapter.KEY_TITLE,
BooksDBAdapter.KEY_GENRE,
BooksDBAdapter.KEY_PRICE,
BooksDBAdapter.KEY_PUBLISH_DATE,
BooksDBAdapter.KEY_DESCRIPTION,
};

//view we want to set results
int[] to = new int[]{R.id.author, R.id.title, R.id.genre, R.id.price, R.id.publish_date, R.id.description};

//create cursor adapter. which exposes data from a Cursor to a ListView
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.search_results, cursor, from, to, 0);
myList.setAdapter(cursorAdapter);
//listview Click listener for selected results
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) myList.getItemAtPosition(position);

//fix this line. modify string value

String author = cursor.getString(cursor.getColumnIndexOrThrow("author"));
String title = cursor.getString(cursor.getColumnIndexOrThrow("title"));
String genre = cursor.getString(cursor.getColumnIndexOrThrow("genre"));
String price = cursor.getString(cursor.getColumnIndexOrThrow("price"));
String publish_date = cursor.getString(cursor.getColumnIndexOrThrow("publish_date"));
String description = cursor.getString(cursor.getColumnIndexOrThrow("description"));


myList.setAdapter(defaultAdapter);

for (int pos = 0; pos < nameList.size(); pos++) {
if (nameList.get(pos).equals(searchValue)) {
position = pos;
break;
}
}

Handler handler = new Handler();
final int finalPosition = position;
handler.post(new Runnable() {
@Override
public void run() {

myList.setSelection(finalPosition);
}
});


searchView.setQuery("", true);
}

cursor.close();
}


}


BooksDBAdapter



public class BooksDBAdapter {
public static final String KEY_ROWID = "rowid";
public static final String KEY_AUTHOR = "author";
public static final String KEY_TITLE = "title";
public static final String KEY_GENRE = "genre";
public static final String KEY_PRICE= "price";
public static final String KEY_PUBLISH_DATE = "date";
public static final String KEY_DESCRIPTION = "description";
public static final String KEY_SEARCH = "searchData";

private static final String TAG = "BooksDBAdapter";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;

private static final String DATABASE_NAME = "BooksData";
private static final String FTS_VIRTUAL_TABLE = "FTSBooksData";
private static final int DATABASE_VERSION = 1;

//Create FTS3 virtual table to provide a more robust and faster serarch
private static final String DATABASE_CREATE =
"CREATE VIRTUAL TABLE " + FTS_VIRTUAL_TABLE + " USING fts3(" +
KEY_AUTHOR + "," +
KEY_TITLE + "," +
KEY_GENRE + "," +
KEY_PRICE + "," +
KEY_PUBLISH_DATE + "," +
KEY_DESCRIPTION + "," +
KEY_SEARCH + "," +
" UNIQUE (" + KEY_TITLE + "));";

private final Context context;

private static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {

super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
Log.w(TAG, DATABASE_CREATE);
db.execSQL(DATABASE_CREATE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + FTS_VIRTUAL_TABLE);
onCreate(db);
}
}

public BooksDBAdapter(Context ctx) {
this.context = ctx;
}

//when we open the db
public BooksDBAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(context);
mDb = mDbHelper.getWritableDatabase();
return this;
}

public void close() {
if (mDbHelper != null) {
mDbHelper.close();
}
}

public long createBooks( String author, String title, String genre, String price, String publish_date, String description) {

ContentValues initialValues = new ContentValues();
String searchValue =
author + " " +
title + " " +
genre + " " +
price + " " +
publish_date + " " +
description;
initialValues.put(KEY_AUTHOR, author);
initialValues.put(KEY_TITLE, title);
initialValues.put(KEY_GENRE, genre);
initialValues.put(KEY_PRICE, price);
initialValues.put(KEY_PUBLISH_DATE, publish_date);
initialValues.put(KEY_DESCRIPTION, description);
initialValues.put(KEY_SEARCH, searchValue);

return mDb.insert(FTS_VIRTUAL_TABLE, null, initialValues);
}


public Cursor searchBooks(String inputText) throws SQLException {
Log.w(TAG, inputText);
String query = "SELECT docid as _id," +
KEY_AUTHOR + "," +
KEY_TITLE + "," +
KEY_GENRE + "," +
KEY_PRICE + "," +
KEY_PUBLISH_DATE + "," +
KEY_DESCRIPTION +
" from " + FTS_VIRTUAL_TABLE +
" where " + KEY_SEARCH + " MATCH '" + inputText + "';";

Log.w(TAG, query);
Cursor mCursor = mDb.rawQuery(query, null);

if (mCursor != null ) {
mCursor.moveToFirst();
//mCursor.close();
}
return mCursor;

}

public boolean deleteAllBooks() {
int doneDelete;
doneDelete = mDb.delete(FTS_VIRTUAL_TABLE, null , null);
return doneDelete > 0;
}


MyAdapter



public class MyAdapter extends BaseAdapter {

private ArrayList myListItems;
private LayoutInflater myLayoutInflater;

public MyAdapter(Context context, ArrayList arrayList) {
myListItems = arrayList;
//get layout inflater
myLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

//how many items on list
@Override
public int getCount() {
return myListItems.size();
}

//get item from specific position in list
@Override
public Object getItem(int i) {
return null;
}

//get position id from list
@Override
public long getItemId(int i) {
return 0;
}

@Override
public View getView(int position, View view, ViewGroup viewGroup) {
//create viewholder reference
ViewHolder holder;
//check to see if reused view is null, if null create new view
if (view == null) {
holder = new ViewHolder();

view = myLayoutInflater.inflate(R.layout.search_results, viewGroup, false);
holder.itemName = (TextView) view.findViewById(R.id.author);
holder.itemName = (TextView) view.findViewById(R.id.title);
holder.itemName = (TextView) view.findViewById(R.id.genre);
holder.itemName = (TextView) view.findViewById(R.id.price);
holder.itemName = (TextView) view.findViewById(R.id.publish_date);
holder.itemName = (TextView) view.findViewById(R.id.description);

//use set tag to store data in view
view.setTag(holder);
} else {
//reuse view
holder = (ViewHolder) view.getTag();
}

//get string item from the set position in arraylist and set it to the textview
String stringItem = myListItems.get(position).toString();
if (stringItem != null) {
if (holder.itemName != null) {
//set the item name on the TextView
holder.itemName.setText(stringItem);
}
}
//return current view
return view;
}
//static class to avoid the calling of "findViewById" every time the getView() method is called.
//willenhance performance
private static class ViewHolder {
protected TextView itemName;
}


}


Aucun commentaire:

Enregistrer un commentaire