Populate ListView with SQLite - android

I am creating an app where you can insert tasks to do and amend them. I currently can view the tasks in a list which I have created, however when I click on the list only the title is shown, although the other entries aren't shown.
Within the entry screen I have code which populates the Entry screen with previous information:
mSaveButton = (ImageButton) findViewById(R.id.diaryform_ib_save);
Log.i(TAG,"Field Title: "+ mTitle);
Intent showTitle = getIntent();
String fieldTitle = showTitle.getStringExtra(Constants.DIARY_TITLE);
Log.i(TAG,"Field Title 2: "+ fieldTitle);
mTitle.setText(fieldTitle);
Intent showEntry = getIntent();
String fieldEntry = showEntry.getStringExtra(Constants.DIARY_ENTRY);
mEntry.setText(fieldTitle);
Log.i(TAG,"Field Entry: "+ mEntry);
Log.i(TAG,"Field Entry 2: "+ fieldEntry);
I have Log messages in there so I can see what information is being given. For fieldTitle the title is passed and for fieldEntry null is passed. When I make both fieldTitle both fields are filled with the title.
Within my ListActivity class I have the following code snippet:
diaryDAO = new DAO(this); //Creates an instance of the DAO
Cursor diaryCursor = diaryDAO.queryDiary(Diary.DiaryItem.LIST_PROJECTION, null, null);
Log.i(TAG, "I get to here!");
String[] diaryDataColumns = { Diary.DiaryItem.COLUMN_NAME_DIARY_TITLE,Diary.DiaryItem.COLUMN_NAME_DIARY_ENTRY };
Log.i(TAG, "Also here");
int[] viewIDs ={ R.id.textView1 };
Log.i(TAG, "Diary Data Col" +diaryDataColumns);
Log.i(TAG, "I'm here");
//Creates backing adapter for the ListView
#SuppressWarnings("deprecation") s
SimpleCursorAdapter diaryAdapter= new SimpleCursorAdapter(
this,
R.layout.activity_diary_list,
diaryCursor,
diaryDataColumns,
viewIDs
);
Log.i(TAG, "Now im here");
this.setListAdapter(diaryAdapter);
Where I create the diaryDataColumns string I tried added the Diary.DiaryItem.COLUMN_NAME_DIARY_ENTRY and it doesn't show within the entry screen BUT when I change the Diary.DiaryItem.COLUMN_NAME_DIARY_TITLE to ENTRY the list view and the entry shows the entry given.
Any ideas? Slightly confused as to what I am doing wrong.
Thanks
edit:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent openItem = new Intent(this, DiaryEntryActivity.class);
Cursor listCursor = (Cursor)l.getAdapter().getItem(position);
openItem.putExtra(Constants.DIARY_TITLE, listCursor.getString(1));
startActivity(openItem); //Starts the intent actions
}

It seems to me you give two columns, but only one text view. The first given columns data will be populated in the text view, but I think, there is no data in the first column, but your second column contains data, and when you switch them, that data will be populated in the text view. Try it out with two textViews.
But I think to work with content provider is an effecient way, there is a good tutorial on vogella.com about it.

Since you are using SQLite, I suggest you look at using SQLiteOpenHelper. Typically, you subclass this class from the Android API and then use it to implement a ContentProvider. The ContentProvider subclass in turn delivers Cursors to your app which can be used by a CursorAdapter. I suggest you start with a SimpleCursorAdapter and then customize it from there. You should also learn about CursorLoaders which allow you to load data from a database on a separate thread. For more details look at http://developer.android.com/guide/topics/ui/layout/listview.html.

Related

Android RecyclerView inside Fragment is not updating Loader content

I have Fragment and it uses RecyclerView Adapter with LoaderManager to list items. RecyclerView i use is from this address. I've implemented LoaderManager in Fragment and gave context of its Activity to RecyclerView.
When i add new item to list, it does not refresh and show new item in list. I use same Adapter and structure on another activity and it works good. But here i use RecyclerView with Loader inside Fragment and it does not refresh list when i add item, instead i have to go back(finish fragment) and enter again.
I have 2 tables like this. First I get cursor from student_course table and from that cursor i get student ids of specific class. Then using data of first cursor, i get second cursor from students table which has list of students from same class. Then i send second cursor to adapter. I do below operation on both onCreateView() and onCreateLoader:
String[] projection0 = {
DatabaseOpenHelper.COL_STUDENT_ID,
DatabaseOpenHelper.COL_COURSE_ID};
String selection0=DatabaseOpenHelper.COL_COURSE_ID + "=?";
String selectionArgs0[]={String.valueOf(courseId)};
mDataset0=getActivity().getContentResolver().query(StudentContentProvider.CONTENT_URI2, projection0,selection0,selectionArgs0,null);
if(mDataset0.getCount()!=0) {
//BATCH
List<String> selectionList = new ArrayList<String>();
mDataset0.moveToFirst();
...
String[] projection1 = {
DatabaseOpenHelper.COLUMN_ID,
DatabaseOpenHelper.COL_STUDENT_NUMBER,
DatabaseOpenHelper.COL_STUDENT_NAME,
DatabaseOpenHelper.COL_STUDENT_CARD_ID,
DatabaseOpenHelper.COL_STUDENT_COLOR};
selection1 = selection1.substring(0, selection1.length() - 2) + ")";
mDataset1 = getActivity().getContentResolver().query(StudentContentProvider.CONTENT_URI1, projection1, selection1, selectionArgs1, null);
}else{
mDataset1=null;
}
...
mAdapter = new studentListAdapter(getActivity(),mDataset1,this);
mDataset1 is students of same class.
1) What might be the problem ? 2) Is there any way to implement LoaderManager class inside
Update 1: When i change selection1 and selectionArgs1 to null, it updates list immediately after i add item. But it shows all students from every class because i didn't specify selection.
Update 2: When i check onLoadFinished() i see that new cursor, after loading new content, is still same as old.
1) I realized that cursor is not changing when new data is added, so when i add new data i call getLoaderManager().restartLoader(LOADER_ID,null,this) (by localBrodCastManager in my case) which reloads cursor (calls onCreateLoader()) and new data is shown on list. (as Suggested here). This does trick.
2) I found that the reason cursor does not change when item is added, because on onCreateLoader() i returned cursor with specific id selection of students, which means cursor will not change until there is change on that items with specific ids i have given. So, if there is new item added, my cursoris not changed, but if one of the items(which is listed) is removed or changed, then cursor is changed. Solution is here.

Filter a listview instead of re-querying the database with more specific criteria

The subject doesn't seem to have been discussed a lot in details so I am gonna explain my situation as well as possible to make it clear and hopefully get some explanations.
My app allows the user to get information about places : there are different menus with different buttons corresponding to categories of places (food/ fastfood, restaurants, ... OR stores/shops, .... and so on). The user clicks on the button of his choice, it will send a request to my database and display a listview with the results. This way :
It is one example, but there are 16 possibilities like this, and everytime it's opening the same activity (ResultListViewActivity) but displaying different content.
I want the user to be able to make more accurate research, so there is a filter mode as you can see on picture 3. The window appearing allows to choose some more criteria. What I planned so far was to fill some variable everytime the user clicks on something. Like if he chooses to pay with a credit card, VALUECARD = X, if budget = something then VALUEBUDGET = Y and so on and when you click on OK it sends all the value package to a method querying the database and open a new listview with the results. It would definitely works, and I know how to do. But I also think it's not really a good way to query the database every time, why not searching directly in the list view ?
I know how to query the database, as my method is working to display listview (see picture 2), but I have no idea how to query a listview, especially when some columns from the database I would use in my filering are not imported in my cursor and then in my listview. I guess I would first have to import every column I might need for filtering.
Here is the code of my method displaying the listview so you see how my cursor is filled and my adapter is made :
private void displayListView() {
// getExtra
Bundle bundle = getIntent().getExtras();
String title = bundle.getString("title", "Choose here :");
String inInterval = bundle.getString("inInterval");
Log.d(TAG, "inInterval = " + inInterval);
poititle.setText(title);
// put the results of the method in a cursor
Cursor c = dbHelper.findPoiInTable(inInterval);
String[] columns = new String[] { DatabaseAdapter.COL_NAME,
DatabaseAdapter.COL_STREET, DatabaseAdapter.COL_WEBSITE,
DatabaseAdapter.COL_TELEPHONE, DatabaseAdapter.COL_REMARKS,
DatabaseAdapter.COL_PRICE };
int[] to = new int[] { R.id.name, R.id.street, R.id.website,
R.id.telephone, R.id.remarks, R.id.price };
cursorAdapter = new SimpleCursorAdapter(this, R.layout.poi_info, c,
columns, to, 0);
ListView listView = (ListView) findViewById(R.id.poilistview);
// Assign adapter to ListView
listView.setAdapter(cursorAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// Comportement des éléments de la listview
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent i = new Intent(getApplicationContext(),
POIActivity.class);
String name = ((TextView) view.findViewById(R.id.name))
.getText().toString();
String website = ((TextView) view.findViewById(R.id.website))
.getText().toString();
String telephone = ((TextView) view
.findViewById(R.id.telephone)).getText().toString();
String remarks = ((TextView) view.findViewById(R.id.remarks))
.getText().toString();
String price = ((TextView) view.findViewById(R.id.price))
.getText().toString();
// i.putExtra(ID_EXTRA, name) ;
i.putExtra(ID_NAME, name);
i.putExtra(ID_WEBSITE, website);
i.putExtra(ID_TELEPHONE, telephone);
i.putExtra(ID_REMARKS, remarks);
i.putExtra(ID_PRICE, price);
startActivity(i);
}
}); }
In this particular case, how could I for example filter the "COL_PRICE" which is in my cursor ? To be more precise, in my filter menu, when the user sets the budget and we get a value, how to use this value in relation to the value from COL_PRICE and keep elements under the given value ?
Thanks for any information !
The easiest solution with your current Code would be using adding a FilterQueryProvider to your adapter, but this will eventually start a new query in your database.
If you really don't want to do a new query on your database, you would have to implement your own custom adapter for your ListView. This will be a whole lot more work than the first solution and is probably slower too.

Using rawQuery to pass _id from listview and populate details of the selection in new activity (Android)

I have an activity with a listview that is displaying the results of a previous listview. The two listview activities are:
List of Cities.
List of Streets within that city.
When I select a Street on my ListView, I then want to populate another activity with certain details of the street that are stored in my database (example, restaurants or points of interest).
I am trying to pass the _id of the street that I clicked and get it in my new activity (just like I did with the City to Street activity) but I'm not able to return any results. Below is my code. I'd appreciate any assistance in trying to figure this one out.
Here is the piece of my code to get the information from clicking on a specific Street. To keep it simple, I'm just trying to display an ID and the name again just to get something to populate from the row:
#Override
protected void onListItemClick(ListView parent, View view, int position, long id) {
//super.onListItemClick(parent, view, position, id);
Intent intent = new Intent(this, Street_Details.class);
Cursor cursor = (Cursor)adapter.getItem(position);
intent.putExtra("Street_ID", cursor.getInt(cursor.getColumnIndex("_id")));
startActivity(intent);
}
And here is my code in my new activity to display some details of that street:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.peak_details);
Intent i = getIntent();
streetId = getIntent().getIntExtra("Street_ID", 0);
db.openDataBase();
Cursor cursor = myDataBase.rawQuery("SELECT _id as _id, City_id, Street FROM Streets WHERE _id = '" +streetId+"'", null);
if (cursor.getCount() == 1)
{
cursor.moveToFirst();
elevation = (TextView) findViewById(R.id.elevation);
elevation.setText(cursor.getString(cursor.getColumnIndex("Street_Id)));
elevation1 = (TextView) findViewById(R.id.elevation1);
elevation1.setText(cursor.getString(cursor.getColumnIndex("Street")));
}
Any help would be great! Thanks for looking.
This is confusing. Are you trying to display the city and its streets in one ListView? That's going to be messy. As far as I can tell, you're doing it with an adapter that contains an array of cursors, and I'm not sure that will work.
Regardless, the parameter for onListItemClicked() that points to an item in the backing data is not position but id. Position is the index of the list item in the ListView; id is the _ID value of row in the Cursor (for cursor adapters) or the index of the data item in the
data. They can be different.
Next, you put the street ID in as the column index of the _id value in the cursor?! This makes no sense to me. In the next activity, you're not going to be selecting on street ID, you're going to be selecting on the index of the street ID column in the cursor.
I'd have to more about your database organization to give you any further direction. However, if I were implementing this, I'd display cities in one activity and streets in the next.
A. Elk pointed out more than one issue with the organization of the activities, but one of those is easily solved: finding the record id (value contained in the '_id' column in the database) based on the cursor id. Here's how I did it:
getListView().setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
c.moveToPosition(position);
String recId = c.getString(0);
Intent intent = new Intent(view.getContext(), DisplayRecordActivity.class);
intent.putExtra(RECORD_ID, recId);
startActivity(intent);
}
});

ListView items sort/reorder and saving changes?

I have a ListView and I can reorder items, but every time I exit from the app and start it again the order goes back to default. I'd appreciate if someone can give me answer and maybe a little snippet of how I can do that.
Example: I have two items and two links. Google and Yahoo. I use drag and drop and ArrayList with that. Everything is fine except I don't know how to save the new order.
I don't know if there is some other way to reorder those items.
I use CWAC-TOUCHLIST to do this.
Here is how far I have got:
private static String[] items={"Google", "Yahoo"};
private static String[] links={"http://google.com", "http://yahoo.com"};
private IconicAdapter adapter=null;
private IconicAdapter1 adapter2=null;
ArrayList<String> array= new ArrayList<String>(Arrays.asList(items));
private ArrayList<String> array2=
new ArrayList<String>(Arrays.asList(links));
/** Called when the activity is first created. **/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TouchListView tlv=(TouchListView)getListView();
adapter=new IconicAdapter();
adapter2=new IconicAdapter1();
setListAdapter(adapter);
setListAdapter(adapter2);
tlv.setOnItemClickListener(itemclick);
tlv.setDropListener(onDrop);
}
private TouchListView.DropListener onDrop =
new TouchListView.DropListener() {
#Override
public void drop(int from, int to) {
String item=(String) adapter.getItem(from);
adapter.remove(item);
adapter.insert(item, to);
String link=(String) adapter2.getItem(from);
adapter2.remove(link);
adapter2.insert(link, to);
}
};
private TouchListView.OnItemClickListener itemclick =
new TouchListView.OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view,
int from, long id) {
String item = adapter.getItem(from);
Toast.makeText(getBaseContext(), "you pick: "+item,
Toast.LENGTH_SHORT).show();
String link = adapter2.getItem(from);
Intent showContent = new Intent(getApplicationContext(),
Web.class);
showContent.setData(Uri.parse(link));
startActivity(showContent);
}
};
Is there a smarter way to do it?
You have to save the lists with their order either to a file or a DB.
When the application starts you have to initialize the ListViews from the saved lists.
When you drag & drop an item, you have to save the changes.
The method you need to change :
Your drop method should, in addition to what it already does, store the changes in a file or a DB.
Instead of the arrays that you pass in the IconicAdapter and IconicAdapter2 constructors (array & array2), you should pass the saved arrays.
You can read in many places how to store data to a file or a SQLite DB. For example, you can find a good tutorial for SQLite here - http://www.vogella.com/articles/AndroidSQLite/article.html#android_requisites (only the first four sections are relevant, since you don't have to use a ContentProvider).
If you choose to use a DB, you can create a table that contains the following columns : item, link & order. In the drop method you'll have to update the order column of all the rows whose order is between from and to (or if the lists are not too big, you can simply update all the rows and set the order to be the index in the array that holds the list).
When you load the table from the DB you should order it by the order column.

Best way to display a large amount of text?

I currently have a list and would like to display a large amount of text once a list item has been clicked. The amount of text will vary depending on the list item that's been clicked, ranging anything from a paragraph to a number of paragraphs.
I'm still very much an Android noob, so any tutorials that you know of that relate to your answer would be most appreciated.
Thank you.
The specifics are up to how you want your App to look and feel, but I would say you cant go wrong with a textView with wrap_content for height and width, nested inside a scroll view.
Probably set that inside a custom dialog to pop up when the list is clicked, or make another activity to just show the text.
Depending on what type of information you are displaying, you might want to just have the ListView item redirect to an activity specifically for displaying this information in a nicely organized manner.
If there is going to be a lot of information (and interactivity such as links), then I recommend the new activity.
Pro: Flow! User can navigate back to your list.
Con: It's a new activity
Otherwise you could use a dialog or similar to show the information on the same activity as the list.
Short sample:
// bind your adapter here from database or wherever
String[] Columns = { "_id", "Name", "Description" };
int[] ItemIDs = { R.id.lbl_ID, R.id.lbl_Name, R.id.lbl_Description };
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor, Columns, ItemIDs);
ListView list_list= (ListView)findViewById(R.id.list);
list_list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView parent, View view, int position, long id)
{
try
{
Intent i = new Intent(getBaseContext(), ViewItemDetail.class);
i.putExtra("ID", ID);
// any other data you need to pass on to your view here. ID should let you select from a database or however you are pulling data
startActivity(i);
}
catch(Exception ex)
{
Log.println(1, "item-click-event", ex.getMessage());
}
}
});
// Then in your activity to get intent data:
Bundle extras = getIntent().getExtras();
if(extras !=null)
{
string ID = extras.getString("ID");
}

Categories

Resources