how to populate custom listview from sqlite database? - android

I have created an android app in which i have to fetch data from sqlite database and set it on custom listview. Problem is that data is not shown. my code is same as a required for showing output.

You need to create a class which extends CursorAdapter. Below is the demo code:
public class PassCursorAdapter extends CursorAdapter {
public PassCursorAdapter(Context context, Cursor c) {
super(context, c,0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_todo,parent,false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView textID = (TextView) view.findViewById(R.id.textView6);
TextView textName = (TextView) view.findViewById(R.id.textView3);
TextView textUser = (TextView) view.findViewById(R.id.textView4);
TextView textPass = (TextView) view.findViewById(R.id.textView5);
int idColumnIndex = cursor.getColumnIndex(PassDBHelper.COLUMN_ID);
int nameColumnIndex = cursor.getColumnIndex(PassDBHelper.PASS_COLUMN_NAME);
int userColumnIndex = cursor.getColumnIndex(PassDBHelper.PASS_COLUMN_USERNAME);
int passColumnIndex = cursor.getColumnIndex(PassDBHelper.PASS_COLUMN_PASSWORD);
String id = cursor.getString(idColumnIndex);
String name = cursor.getString(nameColumnIndex);
String user = cursor.getString(userColumnIndex);
String pass = cursor.getString(passColumnIndex);
textID.setText(id);
textName.setText(name);
textUser.setText(user);
textPass.setText(pass);
}
}
In the newView method you are returning the layout file. This is how your List View layout file will be with 4 Text Views. In the End there is the method bindView where you set the id's.
Now to display the database you need to get the data from the sq-lite database as follows:
private void displayDataBaseInfo() {
PassDBHelper passDBHelper = new PassDBHelper(this);
SQLiteDatabase db = passDBHelper.getReadableDatabase();
String [] columns = {
PassDBHelper.COLUMN_ID,
PassDBHelper.PASS_COLUMN_NAME,
PassDBHelper.PASS_COLUMN_USERNAME,
PassDBHelper.PASS_COLUMN_PASSWORD
} ;
Cursor cursor = db.query(PassDBHelper.TABLE_NAME,columns,null,null,null,null,null);
ListView listView = (ListView)findViewById(R.id.list);
PassCursorAdapter passCursorAdapter = new PassCursorAdapter(this,cursor);
listView.setAdapter(passCursorAdapter);
}//displayDatabaseInfo

Related

How do I change custom CursorAdapter to display only specific rows in the listview for a given fragment?

Three fragments in my app, Fragment1, Fragment2, Fragment3 display contents of a single table in a listview, using a single custom CursorAdapter class, TaskCursorAdapter. Here is the class:
public class TaskCursorAdapter extends CursorAdapter {
public TaskCursorAdapter(Context context, Cursor c) {
super(context, c, 0 /* flags */);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.list_item_task, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
TextView titleTextView = (TextView) view.findViewById(R.id.task_title);
TextView detailsTextView = (TextView) view.findViewById(R.id.task_details);
int titleColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE);
int detailsColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DETAILS);
String taskTitle = cursor.getString(titleColumnIndex);
String taskDetails = cursor.getString(detailsColumnIndex);
if (TextUtils.isEmpty(taskDetails)) {
taskDetails = context.getString(R.string.unknown_task);
}
titleTextView.setText(taskTitle);
detailsTextView.setText(taskDetails);
}
}
The table is specified in the Contract class as TaskEntry. It also has another column named TaskEntry.COLUMN_TASK_STATUS="status". The possible values are 0, 1 or 2. Currently, all the items are displayed in both fragments. But, I want to make it so that only the rows with status=0 are displayed in Fragment1, those with status=1 in Fragment2 and those with status=2 in Fragment3.
I tried the following in bindView method:
int taskStatus = Integer.parseInt(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
if(taskStatus==0) { //code in bindView }
This resulted in displaying only the items with status=0 in all fragments, but it left an empty inflated view in place of the item with status other than 0.
Also, I cannot find a way to pass the information to make it specific to Fragment1.
How should I conditionally display rows based on status value and fragment?
EDIT:
What worked:
Instead of trying this in TaskCursorAdapter, I used conditional query in onCreateLoader method like the following in each fragment:
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String selectionArgs[] = {"<status>"};
String[] projection = {
TaskEntry._ID,
TaskEntry.COLUMN_TASK_TITLE,
TaskEntry.COLUMN_TASK_DETAILS};
return new CursorLoader(this.getActivity(), TaskEntry.CONTENT_URI, projection,
TaskEntry.COLUMN_TASK_STATUS + " = ?", selectionArgs, null);
}
Try this:
public class TaskCursorAdapter extends CursorAdapter {
private int statusCode;
public TaskCursorAdapter(Context context, Cursor c) {
super(context, c, 0 /* flags */);
}
public setStatusCode(int statusCode){
this.statusCode = statusCode;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
int currentStatusCode = Integer.parseInt(cursor.getString(cursor.getColumnIndex(TaskEntry.COLUMN_TASK_STATUS)));
if(statusCode == currentStatusCode){
return LayoutInflater.from(context).inflate(R.layout.list_item_task, parent, false);
} else return null;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
if(view != null){
TextView titleTextView = (TextView) view.findViewById(R.id.task_title);
TextView detailsTextView = (TextView) view.findViewById(R.id.task_details);
int titleColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_TITLE);
int detailsColumnIndex = cursor.getColumnIndex(TaskEntry.COLUMN_TASK_DETAILS);
String taskTitle = cursor.getString(titleColumnIndex);
String taskDetails = cursor.getString(detailsColumnIndex);
if (TextUtils.isEmpty(taskDetails)) {
taskDetails = context.getString(R.string.unknown_task);
}
titleTextView.setText(taskTitle);
detailsTextView.setText(taskDetails);
}
}
}
and do this in each of your fragments, passing in your status codes, respectively:
yourAdapter = new TaskCursorAdapter(this, yourDataCursor);
yourAdapter.setStatusCode(YOUR_STATUS_CODE);
yourListView.setAdapter(yourAdapter);
EDIT (It turns out we can't return null from CursorAdapter#newView()
So I guess you are going to have to filter your cursor in each Fragment before instantiating a new TaskCursorAdapter, and pass in your filtered cursor instead of your original cursor. You can use CursorWrapper class for that. This answer might give you an idea: https://stackoverflow.com/a/7343721/8354184.

ListViewAnimations only works when the Listview has only 1 view/element

I am using ListViewAnimations I am having this weird problem,
the animation is skipped and all of the views are populated if the list contains more than 1 element, but animation works if there is only one element to populate.
class AdapterOutcome extends CursorAdapter {
public AdapterOutcome(Context context, Cursor c, int flags) {
super(context, c, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.outcome_custom_row, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
//finding the Views
TextView amonut = (TextView) view.findViewById(R.id.amount);
ImageView transactionType = (ImageView) view.findViewById(R.id.custom_row_icon);
TextView time = (TextView) view.findViewById(R.id.timeid);
TextView location = (TextView) view.findViewById(R.id.location);
TextView date = (TextView) view.findViewById(R.id.date);
TextView type_icon = (TextView) view.findViewById(R.id.type_icon);
//Creating Cursors for each View
String cursorTranscationType = cursor.getString(cursor.getColumnIndexOrThrow("_transactionType"));
String cursorAmount = cursor.getString(cursor.getColumnIndexOrThrow("_amount"));
String cursorTime = cursor.getString(cursor.getColumnIndexOrThrow("_time"));
String cursorLocation = cursor.getString(cursor.getColumnIndexOrThrow("_location"));
String cursorDay = cursor.getString(cursor.getColumnIndexOrThrow("_day"));
String cursorMonth = cursor.getString(cursor.getColumnIndexOrThrow("_month"));
String cursorYear = cursor.getString(cursor.getColumnIndexOrThrow("_year"));
DateFormat dateformat = DateFormat.getDateInstance(DateFormat.MEDIUM);
// Date myDate = new Date(Integer.parseInt(cursorYear)-1900, Integer.parseInt(cursorMonth)-1, Integer.parseInt(cursorDay));
//set the data from the Cursor to the Views
amonut.setText(String.valueOf("- " + cursorAmount));
time.setText(String.valueOf(cursorTime));
location.setText(String.valueOf(cursorLocation));
// date.setText( dateformat.format(myDate));
if (cursorTranscationType.equals("Purchase")) {
type_icon.setText("P");
}
else{
type_icon.setText("C");
}
}
}
Did you use a custom adapter for your list view? if yes, save the last position of your getView in a global int variable and when next a view need to be populated, use the last position.
if this is not clear enough, post a sample of your code.

Values are not Populating in Listview [duplicate]

This question already has answers here:
Custom Adapter getView() method is not called
(6 answers)
Closed 7 years ago.
I am trying to develop an android application that can display values from multiple tables.
I have used a Base Adapter to display the values since i just need to display the queried values in a list. But when I try to display the values in the list view it is blank.
I am not sure what I have done wrong.
I am Using the below method to query the data from the database to display only the required values.
public Cursor getAssetInStore()
{
SQLiteDatabase db_database = getReadableDatabase();
Cursor c = db_database.rawQuery("SELECT asset_name,warrenty,AssetImage,asset_status FROM `Assets`,`AseetIssued` WHERE Assets.Assetid = AseetIssued.Assetissuedid AND asset_status =?" ,
new String [] {"In Storage"}, null);
return c;
}
The below methods are used to populate the values onto the list view.
private void populateAssetListView()
{
Cursor c = db_database.getAssetInStore();
AssetListView.setAdapter(new AssetListAdapter(this, c));
}
public class AssetListAdapter extends BaseAdapter
{
private Context mContext;
Cursor cursor;
public AssetListAdapter(Context context, Cursor c) {
super();
mContext = context;
cursor =c ;
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View view, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//The layout is assigned to the custome created created in this case it is customeassetview the cales will be displayed as per this list
view = inflater.inflate(R.layout.assetsinstore_placeholder, null);
cursor.moveToPosition(position);
TextView Assetsstatus = (TextView) view.findViewById(R.id.Assetssatutsstore_view);
int status = cursor.getInt(cursor.getColumnIndex("asset_status"));
Assetsstatus .setText(String.valueOf(status));
TextView Assetsname = (TextView) view.findViewById(R.id.Assetstore_name_view);
String Assetname = cursor.getString(cursor.getColumnIndex("asset_name"));
Assetsname.setText(Assetname);
TextView Warrenty = (TextView) view.findViewById(R.id.Assetstore_Warrenty_view);
String CustDesignation = cursor.getString(cursor.getColumnIndex("warrenty"));
Warrenty .setText(CustDesignation);
ImageView AssetImage = (ImageView) view.findViewById(R.id.list_image);
byte[] bb = cursor.getBlob(cursor.getColumnIndex("AssetImage"));
AssetImage.setImageBitmap(BitmapConver.getPhoto(bb));
return view;
}
}
Try to use a cursor adapter in place of a base adapter. Moreover, beware that the position you're passing to the cursor may not be what you think.

OnClickListener on button inside nested ListViews

I'm trying to create a news feed with comments in Android. I'm using a CursorAdapter with a ListView to implement both the news feed and the list of comments on each item. However, I have no idea how to get the text from the correct EditText when the corresponding Button is pressed.
The only thing I'm really sure about is that I'm doing this wrong.
W/View﹕ requestLayout() improperly called by android.widget.ListView{41e85210 V.ED.VC. ......I. 9,71-711,221 #7f07004a app:id/comments} during layout: running second layout pass
Note: the code below obviously doesn't work, since I'm using only one variable commentText for all rows.
database.getComments() returns a Cursor.
database.addUploadComment() just does an sql insert to save the newly created comment.
public class TimelineCursorAdapter extends CursorAdapter {
public TimelineCursorAdapter(Context context, Cursor cursor, boolean autoRequery) {
super(context, cursor, autoRequery);
}
private TimelineCommentCursorAdapter timelineCommentCursorAdapter;
#Override
public View newView(Context context, final Cursor cursor, ViewGroup parent) {
// when the view will be created for first time,
// we need to tell the adapters, how each item will look
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View returnView = inflater.inflate(R.layout.timeline_item, parent, false);
Log.v(this.getClass().getSimpleName(), "newView called");
// get comments
Database database = Database.getDatabase(context);
timelineCommentCursorAdapter = new TimelineCommentCursorAdapter(context, database.getComments(cursor.getInt(cursor.getColumnIndex("_id"))), true);
ListView listView = (ListView) returnView.findViewById(R.id.comments);
listView.setAdapter(timelineCommentCursorAdapter);
Log.d(this.getClass().getSimpleName(), "adapter: " + listView.getAdapter().toString());
returnView.findViewById(R.id.commentText).setTag(cursor.getPosition());
return returnView;
}
EditText commentText;
#Override
public void bindView(View view, Context context, Cursor cursor) {
Log.v(this.getClass().getSimpleName(), "bindView called");
// here we are setting our data
// that means, take the data from the cursor and put it in views
TextView username = (TextView) view.findViewById(R.id.username);
String usernameString = cursor.getString(cursor.getColumnIndex("username"));
if (usernameString != null) {
username.setText(usernameString);
}
TextView status = (TextView) view.findViewById(R.id.status);
String statusString = cursor.getString(cursor.getColumnIndex("bodytext"));
if (statusString != null) {
status.setText(statusString);
}
TextView timestamp = (TextView) view.findViewById(R.id.timestamp);
String timestampString = cursor.getString(cursor.getColumnIndex("datetime"));
if (timestampString != null) {
timestamp.setText(timestampString);
}
// update the comments section as well
Database database = Database.getDatabase(context);
timelineCommentCursorAdapter.changeCursor(database.getComments(cursor.getInt(cursor.getColumnIndex("_id"))));
Log.v(TimelineCursorAdapter.class.getSimpleName(), "commentButton getView");
Button commentButton = (Button) view.findViewById(R.id.commentButton);
commentText = (EditText) view.findViewById(R.id.commentText);
commentButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.v(TimelineCursorAdapter.class.getSimpleName(), "commentButton onClick");
Log.e("POTATO", view.toString());
Database database = Database.getDatabase(view.getContext());
database.addUploadComment(commentText.getText().toString(), (Integer) commentText.getTag());
commentText.setText("");
}
});
}
Just ask if you need some more code.

refresh listview after data has changed from custom adapter

I have seen several posts on this but I cannot seem to follow one well enough to fix my problem.
I am trying to refresh my ListView after I update or delete a record. I am currently using notifyDataSetChanged() however it does not refresh upon deletion. I can delete, and then if i back our and reload my history.java it will show the updates because I am reloading all of the data.
here is my HistoryAdapter.java
public class HistoryAdapter extends BaseAdapter {
private Context mContext;
Cursor cursor;
history historyClass = new history();
MySQLiteHelper db;
public HistoryAdapter(Context context, Cursor cur){
super();
mContext = context;
cursor = cur;
db = new MySQLiteHelper(context);
}
public int getCount(){
// return the number of records in cursor
return cursor.getCount();
}
// getView method is called for each item of ListView
public View getView(final int position, View view, ViewGroup parent){
// inflate the layout for each item of listView
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.history_list_item, null);
// move the cursor to required position
cursor.moveToPosition(position);
final String id = cursor.getString(cursor.getColumnIndex("_id"));
final long deleteId = Long.parseLong(id);
// fetch the information for each card
String pricePerGallon = cursor.getString(cursor.getColumnIndex("pricePerGallon"));
String gallons = cursor.getString(cursor.getColumnIndex("gallons"));
String odometer = cursor.getString(cursor.getColumnIndex("odometer"));
String date = cursor.getString(cursor.getColumnIndex("date"));
String filledOrNot = cursor.getString(cursor.getColumnIndex("filledOrNot"));
String comments = cursor.getString(cursor.getColumnIndex("comments"));
//String milesPerGallon = cursor.getString(cursor.getColumnIndex("miledPerGallon"));
String totalSpent = cursor.getString(cursor.getColumnIndex("totalSpent"));
// get the reference of TextViews
TextView textViewPricePerGallon = (TextView) view.findViewById(R.id.cardPrice);
TextView textViewGallons = (TextView) view.findViewById(R.id.cardGallons);
TextView textViewOdometer = (TextView) view.findViewById(R.id.cardOdometer);
TextView textViewDate = (TextView) view.findViewById(R.id.cardDate);
TextView textViewFilledOrNot = (TextView) view.findViewById(R.id.cardFilledOrNot);
TextView textViewComments = (TextView) view.findViewById(R.id.cardComments);
//TextView textViewMilesPerGallon = (TextView) view.findViewById(R.id.mpg);
TextView textViewTotalSpent = (TextView) view.findViewById(R.id.usd);
TextView textViewDeleteButton = (TextView) view.findViewById(R.id.deleteButton);
// Set the data to each TextView
textViewPricePerGallon.setText(pricePerGallon);
textViewGallons.setText(gallons);
textViewOdometer.setText(odometer);
textViewDate.setText(date);
textViewFilledOrNot.setText(filledOrNot);
textViewComments.setText(comments);
//textViewMilesPerGallon.setText(milesPerGallon);
textViewTotalSpent.setText(totalSpent);
final HistoryAdapter historyAdapter = this;
textViewDeleteButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.d("History Adapter", "" + deleteId);
//need to delete here
deleteRecord(deleteId);
historyAdapter.notifyDataSetChanged();
}
});
return view;
}
public Object getItem(int position){
return position;
}
public long getItemId(int position){
return position;
}
private void deleteRecord(long id){
db.deleteGasLog(id);
}
}
here is my history.java which sets the adapter and creates the listview
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.history);
context = this;
initViews();
cursor = db.getAllLogs();
// Create the Adapter
historyAdapter = new HistoryAdapter(this, cursor);
// Set the adapter to ListView
listContent.setAdapter(historyAdapter);
}
I guess you will need to get a new cursor.
Try moving this
cursor = db.getAllLogs();
into the adapter and call it again before the notifyDataSetChanged() call.
You are deleting the row but you are never updating or getting a new cursor, which has the result set the adapter uses to layout the list. You need to give the adapter a new cursor after you delete a row, then call notifyDatasetChanged(). If you use SimpleCursorAdapter
instead of BaseAdapter, you can use its swapCursor() method to set the new cursor.
Make sure to call:
registerDataSetObserver(...)
from your BaseAdapter subclass.
Pass it the reference to your DataSetObserver implementation. Possibly through an inner class of HistoryAdapter:
public class HistoryAdapter extends BaseAdapter {
. . .
public class MyDataSetObserver extends DataSetObserver {
public void onChanged() {
// Data Set changed.... do something...
}
public void onValidated() {
// Your implementation here
}
}
. . .
public HistoryAdapter(Context context, Cursor cur) {
. . .
registerDataSetObserver(new MyDataSetObserver());
. . .
}
}
HTH

Categories

Resources