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.
Related
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.
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
I am new to android..and my question is:
I am making one android Application in which I have one RadioGroup with two Radiobutton
btnA and btnB along with some other Parameters.
if btnA is Checked than value in database is 1 and if btnB is selected then Value in Database is 0.
I am retrieving Data from database while showing My Listview.
Now My Question is I want to display Listview with listItem like :
imgA if Value From Database is 1 .
imgB if Value from Database is 0.
How to do it???
I tried this
private Integer[] Images = {R.drawable.imgA,R.drawable.imgB};
Cursor cur = dop.getData();
if(cur!= null && cur.getCount()>0)
{
if(cur.moveToFirst()){
do {Integer btnType= cur.getInt(cur.getColumnIndex(databaseName.TableName.ColumnName));
if(btnType== 1){ImageId = Images[0];}
else if(btnType== 0){ImageId= Images[1];}}
//other Params
}while (cur.moveToNext());
}
Adapter myAdp = new Adapter(Activity.this,ImageId,para);
myList.setAdapter(myAdp);
My Adapter is Like
public class Adapter extends BaseAdapter {
public Context context;
public ArrayList<String>Param1;
public int ImageId;
public Adapter(Context context,int ImageId,ArrayList<String>Param1)
{
this.context = context;
this.ImageId = ImageId;
this.Param1= Param1;
}
public int getCount(){return param1.size();}
public Object getItem(int Position){return null;}
public long getItemId(int Position){return 0;}
public class viewHolder{
TextView tvParam1;
ImageView imgType;
}
#Override
public View getView(int Position,View Child,ViewGroup Parent)
{
viewHolder vHolder;
LayoutInflater inflator;
if(Child == null)
{
inflator = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Child = inflator.inflate(R.layout.list_row,null);
vHolder = new viewHolder();
vHolder.tvparam1 = (TextView)Child.findViewById(R.id.txtParam1);
vHolder.imgType = (ImageView)Child.findViewById(R.id.imgType);
Child.setTag(vHolder);
}
else {vHolder = (viewHolder)Child.getTag();}
vHolder.tvParam1.setText(Param1.get(Position));
vHolder.imgType.setImageResource(ImageId);
return Child;
}
}
my Problem is I am getting same image for all list items.
but I want ImgA for btnA and imgB for btnB.
How to resolve this???
I got solution for this issue
what i done is: I took Integer Arraylist for storing my Images
In my Main Activity:
public int[] Images = {R.drawable.imgA,R.drawable.imgB};
public ArrayList<Integer>ImageId = new ArrayList<Integer>();
int i = 0;
if(cur.moveToFirst()){
if(btnType == 1)
{
ImageId.add(Images[0]);
}
else if(btnType == 0)
{
ImageId.add(Images[1]);
}
} while(cur.moveToNext());
also in myAdapter: I jst changed Integer Array to Integer Arraylist for Image
this solve my Problem
Take an array of ImageId and save the id in that array in specific positions.
int i = 0;
if(cur.moveToFirst()){
do {Integer btnType= cur.getInt(cur.getColumnIndex(databaseName.TableName.ColumnName));
if(btnType== 1){ImageId[i] = Images[0];}
else if(btnType== 0){ImageId[i] = Images[1];}}
i++;
} while(cur.moveToNext());
Now inside your adapter load the images like this
vHolder.imgType.setImageResource(ImageId[Position]);
You've logical error in your code.
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
I asked a question on here about a week or so ago about a custom spinner and got led to this guide. http://app-solut.com/blog/2011/03/using-custom-layouts-for-spinner-or-listview-entries-in-android/
I followed it and I've tried adapting it to work with my code and pull the results from a database onto the spinner but it keeps crashing.
This is the code for the spinner.
public class EditTeam extends Activity {
private final List<SpinnerEntry> spinnerContent = new LinkedList<SpinnerEntry>();
private Spinner D1Spinner;
private final ETSpinnerAdapter D1Adapter = new ETSpinnerAdapter(spinnerContent, this);
DataBaseHelper myDbHelper = new DataBaseHelper(this);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.editteam);
myDbHelper = new DataBaseHelper(this);
myDbHelper.openDataBase();
fillSpinner();
}
private void fillSpinner() {
Cursor c = myDbHelper.FetchDrivers();
startManagingCursor(c);
// create an array to specify which fields we want to display
String[] from = new String[]{"FirstName", "LastName"};
// create an array of the display item we want to bind our data to
int[] to = new int[]{android.R.id.text1};
spinnerContent.add(new SpinnerEntry(1, null, "Test"));
//adapter.setDropDownViewResource( R.layout.spinner_entry_with_icon );
D1Spinner = (Spinner) findViewById(R.id.spr_Driver1);
D1Spinner.setAdapter((SpinnerAdapter) D1Adapter);
}
}
And I am using the two classes from that contacts example which are un-modified at the moment.
As you can see I'm trying to just manually add one item at the moment but it just crashes when you load it.
This seems to be the breaking point?
05-25 15:17:34.773: E/AndroidRuntime(241): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.f1manager.android/com.f1manager.android.EditTeam}: java.lang.ClassCastException: com.f1manager.android.ETSpinnerAdapter
Any ideas would be great.
Thanks.
ETSpinnerAdapter Code (Unmodified from the original code in the example):
public class ETSpinnerAdapter {
private final List<SpinnerEntry> content;
private final Activity activity;
public ETSpinnerAdapter(List<SpinnerEntry> content, Activity activity) {
super();
this.content = content;
this.activity = activity;
}
public int getCount() {
return content.size();
}
public SpinnerEntry getItem(int position) {
return content.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
final LayoutInflater inflater = activity.getLayoutInflater();
final View spinnerEntry = inflater.inflate(
R.layout.spinner_entry_with_icon, null); // initialize the layout from xml
final TextView contactName = (TextView) spinnerEntry
.findViewById(R.id.spinnerEntryContactName);
final ImageView contactImage = (ImageView) spinnerEntry
.findViewById(R.id.spinnerEntryContactPhoto);
final SpinnerEntry currentEntry = content.get(position);
contactName.setText(currentEntry.getContactName());
//contactImage.setImageBitmap(currentEntry.getContactPhoto());
return spinnerEntry;
}
}
It would seem like your ETSpinnerAdapter is not a SpinnerAdapter as your are getting a class cast exceptin. Maybe you can post your code for the ETSpinnerAdapter?