Multiple ListViews in ExpandableListView or nested ListViews - android

I have been trying to import multiple Listviews inside another "mother" Listview.
I have a class where the ListViews are created and then the Activity class which call these views. The only thing I managed to do is fill the "mother" with ListPerms# entries(the objects I guess)
Here is my class for multiple ListViews
public ListPerms(Context context, String a, int docid) {
super(context);
table=a;
did=docid;
list= (ListView) findViewById(R.id.specific_perm_list);
getdata(list,ar_list);
}
private void getdata( ListView list, ArrayList<String> arlist){
Database openHelper = new Database(getContext());
myDB = openHelper.getReadableDatabase();
myDB=SQLiteDatabase.openDatabase("data/data/com.example.login2/databases/aeglea", null, SQLiteDatabase.OPEN_READONLY);
try{fill(list,arlist);}catch(Exception e){Log.e("NAT EXISTANT","THIS->"+e);}
}
private void fill( ListView list, ArrayList<String> arlist){
Cursor temp = null;
Cursor buffer = null;
String type_from_table = null;
String[] items = null;
if(table=="med") {type_from_table = "medication";}
if(table=="test") {type_from_table = "test";}
if(table=="all") {type_from_table = "allergy";}
if(table=="proc") {type_from_table = "procedure";}
if(table=="cond") {type_from_table = "condition";}
if(table=="vacc") {type_from_table = "vaccine";}
temp = fetchOption("SELECT * FROM permission WHERE did="+did+" AND type='"+type_from_table+"'");
if(temp.getCount()>0){
buffer = fetchOption("SELECT * FROM user_"+table+" WHERE id="+temp.getString(temp.getColumnIndex("fileid")));
items = new String[] {buffer.getString(buffer.getColumnIndex("name"))};
arlist.addAll( Arrays.asList(items) );
listAdapter = new ArrayAdapter<String>(getContext(), R.layout.item, arlist);
for(int i=1;i<temp.getCount();i++){
temp.moveToNext();
buffer = fetchOption("SELECT * FROM user_"+table+" WHERE id="+temp.getString(temp.getColumnIndex("fileid")));
listAdapter.add(buffer.getString(buffer.getColumnIndex("name")));
}
list.setAdapter(listAdapter);
}else{
items = new String[] { "None."};
arlist.addAll( Arrays.asList(items) );
listAdapter = new ArrayAdapter<String>(getContext(), R.layout.item, arlist);
list.setAdapter(listAdapter);
}
}
And the Activity class follows where(now) I have an ExpandableListView, but I'm really noob to understand how ELV works
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.docp);
general = (ExpandableListView) findViewById(R.id.Tot_perm_list);
//random data
}
protected void onResume(){
super.onResume();
ListPerms me = new ListPerms(getApplicationContext(),"med",did);
ListPerms te = new ListPerms(getApplicationContext(),"test",did);
ListPerms all = new ListPerms(getApplicationContext(),"all",did);
ListPerms proc = new ListPerms(getApplicationContext(),"proc",did);
ListPerms cond = new ListPerms(getApplicationContext(),"cond",did);
ListPerms vacc = new ListPerms(getApplicationContext(),"vacc",did);
me.setActivated(isChild());
te.setActivated(isChild());
all.setActivated(isChild());
proc.setActivated(isChild());
cond.setActivated(isChild());
vacc.setActivated(isChild());
list.add(me);
list.add(te);
list.add(all);
list.add(proc);
list.add(cond);
list.add(vacc);
general.setAdapter(listAdapter);
general.addChildrenForAccessibility(list);
//what do I do
}
Advice on how to do ListView{LV,Lv ... } or ExpandableListView{LV, LV ....}

Per my understanding it's not a good idea to incorporate two or more list views into one. You'll definitely have issues with scrolling (of course, some dirty hacks can help to fix it) and probably, performance will be way worst than for single list.
I would suggest You to go with ExpandableList and ExpandableListAdapter. To make lists into one You will need to compose it's adapters.
e.g. it could looks like the following:
...
// Your implementation of ExpandableListAdapter
// To store all 'child' adapters, it should be filled by the owner
SparseArray<BaseAdapter> mChildAdapters = new SparseArray<BaseAdapter>();
#Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final BaseAdapter childAdapter = mChildAdapters.get(groupPosition);
View view = null;
if (childAdapter != null) {
view = childAdapter.getView(childPosition, convertView, parent);
}
return view;
}
#Override
public int getChildrenCount(int groupPosition) {
int childrenCount = 0;
final BaseAdapter childAdapter = mChildAdapters.get(groupPosition);
if (childAdapter != null) {
childrenCount = mChildAdapter.getCount();
}
return childrenCount;
}
...
Please note, the above code is just a draft, but I hope the idea is clear from it. The only trick You've might face with this approach - convertView You've received in one childAdapter might be from another, so some (quite trivial) checks should be applied before reusing convertView.
Also, expandable list would give you nice possibility to provide every list with the header (via groupView).

Related

sqlite database on listview

I'm creating an android book that has 6 season whithin sqlite database but listview take several seconds to load data.
I know that I sholud implement onscroll methode to do this,but I don't know how manage it
my code is:
public class list_story extends ListActivity{
private database db;
private String[] Name;
private String sea;
Context c;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.list_story);
db = new database(this);
Bundle ex = getIntent().getExtras();
sea = ex.getString("sea");
refresh();
setListAdapter(new AA());
}
class AA extends ArrayAdapter<String>{
public AA(){
super(list_story.this,R.layout.row_list,Name);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater in = getLayoutInflater();
View row = in.inflate(R.layout.row_list, parent,false);
txt.setText(Name[position]);
return (row);
}
}
private void refresh(){
db.open();
int s =db.Story_count("content", sea);
Name = new String[s];
Fav=new String[s];
Tasvir=new String[s];
Scientific=new String[s];
English=new String[s];
for (int i = 0; i < s; i++) {
Name[i]=db.Story_display(i, sea, "content", 1);
Fav[i]=db.Story_display(i, sea, "content", 4);
Tasvir[i]=db.Story_display(i, sea, "content", 5);
Scientific[i]=db.Story_display(i, sea, "content", 6);
English[i]=db.Story_display(i, sea, "content", 7);
}
db.close();
}
}
Basically every time you try to inflate a new view, you will literally inflate a new view. The problem with that is if you have 100 plus items to put into the list view, well that's 100+ views you've defined. That's extremely inefficient. Use the ViewHolder pattern for ListView, or use a the RecyclerView. Better yet use the RecyclerView. There's a lot of information on the web for both of those. Just look up "how to use ViewHolder in a list view"
If you are only using a single text field and a db i would recomend you to use a simpleCursorAdapter :
db = new DBAdapter(this);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1,
db.getAllTitles(),
new String[] { "title" },
new int[] { android.R.id.text1 });
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
If you have further questions check this great example https://thinkandroid.wordpress.com/2010/01/09/simplecursoradapters-and-listviews/

How to add multiple items in Listview Android

I'm working on an Android application of booking medicine offline. I have used ListView for Cart, but whenever I add a new item in cart, my previous item get replaced.
L1 = imageacidity
L2 = imagecough
if(msg.toString().equals("L1")) {
adapter = new ContactImageAdapter(this, R.layout.list, imageacidity);
ListView dataList = (ListView) findViewById(R.id.list);
dataList.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
if(msg.toString().equals("L2"))
{
adapter = new ContactImageAdapter(this, R.layout.list, imagecough);
ListView dataList = (ListView) findViewById(R.id.list);
dataList.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
Here I have 5 elements in imageacidity and Imagecough Array. Whenever I select 1 item, it gets added in cart, but when I try to select another item it get replaced with new one.
You have to Add the element inside your adapter.
I will post a custom Adapter and show you how to add elements properly.
Adapter:
public class YourAdapter extends BaseAdapter {
List<String> itens;
private Context mContext;
private static LayoutInflater inflater = null;
public YourAdapter(Context context, List<String> itens){
this.itens = itens;
mContext = context;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return itens.size();
}
public String getItem(int position) {
return itens.get(position);
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.list_row, parent, false);
String msg = itens.get(position);
TextView tx = vi.findViewById(R.id.your_id);
tx.setText(msg);
return vi;
}
public void addItem(String item){
itens.add(item);
}
public void addItens(List<String> itens){
this.itens.addAll(itens);
}
}
ListView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new CustomAdapter(this,yourListOfItens);
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
You can set initial data on constructor of adapter, or use methods addItem and addAll on a click button for example.
The problem you are describing of the data being removed is happening because making a new ContactImageAdapter and calling setAdapter, which will completely remove the data that was already in the ListView.
If you want to properly implement the code in the question, you need something like this.
String msg = ""; // TODO: get this String value
ListView dataList = (ListView) findViewById(R.id.list);
// TODO: Define a single List to store the data and use that in *one* adapter
List<Contact> contacts = new ArrayList<Contact>();
adapter = new ContactImageAdapter(this, R.layout.list, contacts);
dataList.setAdapter(adapter);
// TODO: Replace this with the object to add to the adapter
Contact contact = null;
if(msg.equals("L1")) {
// TODO: Use whatever values you want for "L1"
int img = R.drawable.bati_acidity_1;
String name = "Amlapitta";
String price = "price 170";
contact = new Contact(img, name, price);
}
else if(msg.equals("L2")) {
// TODO: Use whatever values you want for "L2"
int img = R.drawable.bati_acidity_2;
String name = "Amlapitta2";
String price = "price 270";
contact = new Contact(img, name, price);
}
if (contact != null) {
contacts.add(contact);
adapter.notifyDataSetChanged();
}
Another problem is that you are calling notifyDataSetChanged without actually changing the datasets of imageacidity or imagecough.
You can use an algorithm (logic) on the InputListAdapter checking and verifying if there is a MedicineVO (Value Object Pattern) item on old list before the calling notyChange(..) method. In addition, you can wrapping the logic in other class such as MedicineLogic to improve the adapter readability.
See the sample code below:
public class MedicineInputListAdapter extends ArrayAdapter<MedicineVo> {
public static final int[] COLORS = new int[] { Color.WHITE, Color.BLUE };
private Context mContext;
private List<MedicineVo> medicineVos;
private MedicineVo medicineVoActual;
public BasePreOSPreventivaCorretivaInputListAdapter(Context context, int resource, List<MedicineVo> medicineVos) {
super(context, resource, medicineVos);
this.medicineVoActual = new MedicineVo();
this.medicineVos = new ArrayList<MedicineVo>();
this.medicineVos.addAll(medicineVos);
this.mContext = context;
}
private static class ViewHolder {
TextView mMedicineTextView;
//------------------------------------------------------
// others Android view components
//------------------------------------------------------
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
//------------------------------------------------------
// mapper from xml to view and add itens to holder
//------------------------------------------------------
//------------------------------------------------------
// add event action to the mMedicineTextView
//------------------------------------------------------
viewHolder.mMedicineTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TextView textView = (TextView) view;
MedicineVo medicineVo = (MedicineVo) textView.getTag();
boolean selected = medicineVo.getSelected();
if (selected) {
/*do it*/
}
refreshPreOSMaterialWhenUpdate(preOSMaterialVo);
}
});
convertView.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) convertView.getTag();
}
//------------------------------------------------------
// get item and adjust color
//------------------------------------------------------
MedicineVo item = getItem(position);
/*do it*/
return convertView;
}
public void refreshMedicineListWhenUpdate(MedicineVo medicineVo){
List<MedicineVo> newMedicineVos = new ArrayList<MedicineVo>();
for (MedicineVo medicineVoOnList : medicineVos) {
if( StringUtils.isNull(medicineVoOnList.getId()) )
continue;
if( MedicineLogic.existsOnList(medicineVos, medicineVoOnList) )
continue;
/* others checks if necessary */
newMedicineVos.add(medicineVoOnList);
}
medicineVos.addAll(newMedicineVos);
}
}
If you can't select more but only one item of your ListView, this might help.As others have commented on the question, changing the adapter of a ListView can clear the selection too, but as I supposed the code you've posted is inside onCreate (or other kind of initialization) so setting the adapter there won't affect the selection (since there can't be selection without items... :) )

Pre-fill the CheckedTextViews in a ListView

Here is my first question on StackOverFlow, I usually always find an answer by myself but I am really stuck on a weird problem that I will explain here:
I implemented a ListView in a fragment activity, this listview contains a list of categories related to the current record that I get from the SQLLite database.
All is working fine, I created a SimpleCursorAdapter to retrieve the data from the DB and I display the categories correctly in the ListView.
The problem is related to the pre-fill of the checkboxes (it is a multiselection list), depending on how I try to pre-check the checkboxes, I get 2 cases:
First, the checkboxes are well pre-checked, but I cannot toggle the checkboxes anymore by clicking them. Second the click toggle well the checkboxes, but they are not pre-checked anymore...
Here is the part of the code where I have the problem:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
View v = inflater.inflate(R.layout.rate_fragment, container,false);
dbCategories = "";
displayCategories = resources.getText(R.string.no_categories).toString();
/** INITIALIZATION */
mViewSwitcher = (ViewSwitcher)v.findViewById(R.id.profileSwitcher);
/** Edition view */
rateGroup = (RadioGroup)v.findViewById(R.id.rate_group);
rateOne = (RadioButton)v.findViewById(R.id.one_button);
rateOne.setTag(1);
rateTwo = (RadioButton)v.findViewById(R.id.two_button);
rateTwo.setTag(2);
rateThree = (RadioButton)v.findViewById(R.id.three_button);
rateThree.setTag(3);
rateFour = (RadioButton)v.findViewById(R.id.four_button);
rateFour.setTag(4);
rateFive = (RadioButton)v.findViewById(R.id.five_button);
rateFive.setTag(5);
descET = (EditText)v.findViewById(R.id.editdescription);
descTextSize = descET.getTextSize();
descET.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
categoriesTV_edit = (TextView)v.findViewById(R.id.edit_categories);
categoriesBT = (Button) v.findViewById(R.id.select_categories);
categoriesBT.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
View categoriesListTitle = getActivity().getLayoutInflater().inflate(R.layout.category_list_title, null);
AlertDialog.Builder alt_bld = new AlertDialog.Builder(v.getContext()).setCustomTitle(categoriesListTitle);
categories = db.getAllCategoriesByRate(currentRate);
categoriesList = new ListView(getActivity());
categoriesList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
categoriesList.setClickable(true);
String[] fromColumns = new String[] {
DatabaseHandler.CATEGORY_NAME
};
int[] toViews = new int[]{
R.id.cat_checked
};
//mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_multiple_choice, categories, fromColumns, toViews, 0);
mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.category_item, categories, fromColumns, toViews, 0);
mAdapter.setViewBinder(new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == 1) {
CheckedTextView categRow = (CheckedTextView) view;
String catName = cursor.getString(1);
mAdapter.setViewText((TextView) view, catName);
int catChecked = cursor.getInt(2);
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
categRow.setChecked(catChecked==1);
int catID = cursor.getInt(0);
categRow.setTag(catID);
return true;
}
else {
return false;
}
}
});
categoriesList.setAdapter(mAdapter);
alt_bld.setView(categoriesList);
To have one case or another, all depends on these 2 lines:
//boolean checkedCat = catChecked==1;
//categoriesList.setItemChecked(cursor.getPosition(),checkedCat);
If they are commented, the checkboxes are not pre-checked, but the toggle on the clicks is working. But if I comment these lines out, the toggle is not working anymore but the categories are prechecked.
What I also don't understand is that this line is not working:
categRow.setChecked(catChecked==1);
But this one is working well (I succeed to retrieve the tag):
categRow.setTag(catID);
So I hope someone will succeed to explain to me what I do wrong, I guess there is something I misunderstood here...
NOTE: I get 3 columns from the cursor "categories", first one is the ID of the category, second one is the name, and third one is the status: checked or not (1 or 0).
Thanks in advance for your time.
Finally I ended up creating my own custom adapter, this way I could at least understand more easily what was happening.
I had to create actually several multiselect lists, some populated with data from the database, others from the shared preferences.
For this one displaying data from the DB, I created the following adapter (I commented out the lines about the icons because I did not set them up yet):
public class CategoriesLVAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private List<Category> categoriesList;
// Constructor
public CategoriesLVAdapter(Context c, List<Category> categories_list){
mContext = c;
mInflater = LayoutInflater.from(c);
categoriesList = categories_list;
}
public List<Category> getCategoriesList(){
return categoriesList;
}
#Override
public int getCount() {
return categoriesList.size();
}
#Override
public Object getItem(int position) {
return categoriesList.get(position);
}
#Override
public long getItemId(int position) {
return categoriesList.get(position).getID();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.categories_list_row, null);
//convertView.setLayoutParams(new ListView.LayoutParams(200, 90));
holder = new ViewHolder();
holder.title = (TextView) convertView.findViewById(R.id.categories_list_row_tv);
//holder.icon = (ImageView) convertView.findViewById(R.id.categories_list_row_iv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//holder.icon.setImageResource(categoriesList.get(position).getDrawableID());
//holder.icon.setAdjustViewBounds(true);
//holder.icon.setScaleType(ImageView.ScaleType.CENTER_CROP);
holder.title.setText(categoriesList.get(position).getName());
return convertView;
}
static class ViewHolder {
TextView title;
//ImageView icon;
}
}
In my activity, I use this adapter when the AlertDialog is called to populate the ListView, then I pre-select the categories using the last ones saved in the shared preferences:
private void categoriesFilter(){
AlertDialog.Builder alt_bld = new AlertDialog.Builder(this);
alt_bld.setTitle(resources.getText(R.string.select_categories).toString());
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.categories_list,(ViewGroup) findViewById(R.id.categories_layout_root));
categoriesLV = (ListView) layout.findViewById(R.id.categories_list);
alt_bld.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String selectedCategoriesString = getSelectedValues(categoriesLV);
//Update the shared preferences
prefs.edit().putString(RateDayApplication.PREF_KEY_CATEGORIES, selectedCategoriesString).commit();
updateFilterDisplay(resources.getText(R.string.cat_title).toString(), selectedCategoriesString, searchedCategoriesTV, "Category");
}
});
alt_bld.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
String selectedCategoriesString = prefs.getString(RateDayApplication.PREF_KEY_CATEGORIES, new String());
categoriesLV.setAdapter(new CategoriesLVAdapter(this, categoriesList));
String[] selectedCategoriesArray = selectedCategoriesString.split(",");
int categoriesLVLength = categoriesLV.getCount();
for(int i = 0; i < categoriesLVLength; i++){
int categoryID = ((Category) categoriesLV.getItemAtPosition(i)).getID();
if(Arrays.asList(selectedCategoriesArray).contains(String.valueOf(categoryID))){
categoriesLV.setItemChecked(i, true);
}
}
alt_bld.setView(layout);
AlertDialog alert = alt_bld.create();
alert.show();
}
Finally here is the function I call from my database handler to get the list of catagories:
// Getting All Categories By ID desc
public List<Category> getCategoriesList() {
String selectQuery = "SELECT " + CATEGORY_ID + ", " + CATEGORY_NAME + " FROM " + CATEGORY_TABLE + " ORDER BY " + CATEGORY_ID + " ASC";
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
List<Category> categoriesList = new ArrayList<Category>();//String[] categoriesList = {};
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Category category = new Category(cursor.getInt(0), cursor.getString(1), false);
categoriesList.add(category);
} while (cursor.moveToNext());
}
cursor.close();
db.close();
return categoriesList;
}
I think my problem before was coming from the fact that the function "setItemChecked" is a little misleading because it does not mean necessarily that anything is checked.
When you use the function "setItemChecked", the item in the list view becomes selected, with or without a checkbox (my rows only contain text views).
The rows selected in my list appear in a different color, and that's enough in my opinion for a simple multi selection list.
The layouts I used are quite simple, "categories_list" contains a ListView in a LinearLayout and "categories_list_row" contains a TextView in a LinearLayout.
Hope it may guide someone!

arrayadapter error when created outside onCreate

I have an ArrayAdapter that I use to fill a listview, but I'm unable to create it outside the oncreate event, but at that time I don't have the data.
public class CusPickup extends Activity {
private OrdersReady orderready_data[];
private ListView lView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.orders);
Here I will get a null point exception.
OrderReadyAdapter adapter = new OrderReadyAdapter(this,R.layout.listview_item_row, orderready_data);
lView = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
lView.addHeaderView(header);
lView.setAdapter(adapter);
getData();
}
}
Here I get the data from HTTP get.
private final Handler handler = new Handler() {
#Override
public void handleMessage(final Message msg) {
progressDialog.dismiss();
String bundleResult = msg.getData().getString("RESPONSE");
int TotalRecords = myResult.d.results.size();
for (int i = x; i < TotalRecords; i++ ) {
orderready_data[i] = new OrdersReady(myResult.d.results.get(i).myStr, myDate ,invResult.d.results.get(i).numberStr, invResult.d.results.get(i).qtyInt, myAmount)
}
}
}
If I place the OrderReadyAdapter her I get a code error with a fix "change OrderReadyAdapter(Context, Int, OrdersReady[]) to OrderReadyAdapter(Handle, Int, OrdersReady[]) if I change it I will get more errors.
Also I'm not sure if my declaration of the private OrdersReady orderready_data[] is correct, because if I declare it in code I would declare it like this: OrdersReady orderready_data[] = new OrdersReady[TotalRecords];
Thanks for any help.
New Adapter
public class OrderReadyAdapter extends ArrayAdapter<OrdersReady>{
Context context;
int layoutResourceId;
ArrayList<OrdersReady> data = null;
public OrderReadyAdapter(Context context, int layoutResourceId, ArrayList<OrdersReady> orderReadyArray) {
super(context, layoutResourceId, orderReadyArray);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = orderReadyArray;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
OrderHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new OrderHolder();
holder.mytxt1 = (TextView)row.findViewById(R.id.mytxt1);
holder.mytxt2 = (TextView)row.findViewById(R.id.mytxt2);
holder.mytxt3 = (TextView)row.findViewById(R.id.mytxt3);
holder.mytxt4 = (TextView)row.findViewById(R.id.mytxt4);
holder.mytxt5 = (TextView)row.findViewById(R.id.mytxt5);
row.setTag(holder);
}
else
{
holder = (OrderHolder)row.getTag();
}
OrdersReady orderready = data.get(position);
holder.mytxt1.setText(orderready.place);
holder.mytxt2.setText(orderready.Date);
holder.mytxt3.setText(orderready.invoice);
holder.mytxt4.setText(String.valueOf(orderready.Qty));
holder.mytxt5.setText(String.valueOf(orderready.Amount));
return row;
}
static class OrderHolder
{
TextView mytxt1;
TextView mytxt2;
TextView mytxt3;
TextView mytxt4;
TextView mytxt5;
}
}
I suggest you change the OrdersReady[] into ArrayList. Initialize it in your onCreate method. Also make the orderReady adapter into a class field.
orderReadyArray = new ArrayList<OrderReady>();
ordersReadyAdapter = new OrderReadyAdapter(this,R.layout.listview_item_row, orderReadyArray);
lView = (ListView)findViewById(R.id.listView1);
View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
lView.addHeaderView(header);
lView.setAdapter(ordersReadyAdapter);
This should initialize an empty listview as you don't have the data yet.
When you receive OrdersReady data from the server, update orderReadyArray as such:
orderReadyArray.clear(); // remove old data
for (int i = x; i < TotalRecords; i++ ) {
orderReadyArray.add(data); // add new data one by one
}
ordersReadyAdapter.notifyDataSetChanged(); // this forces the listview to repaint
Alternatively:
You can create a new adapter and assign it to the listview once you receive the data:
List<OrderReady> orderReadyArray = new ArrayList<OrderReady>(); // create a new array to hold data
for (int i = x; i < TotalRecords; i++ ) {
orderReadyArray.add(data); // add new data one by one
}
OrderReadyAdapter ordersReadyAdapter = new OrderReadyAdapter(this,R.layout.listview_item_row, orderReadyArray);
lView.setAdapter(ordersReadyAdapter);
This should update your list. If you still do not see the items, the problem is in the adapter, perhaps you are inflating the row incorrectly in getView() method.

How to use notifyDataSetChanged

My project simplify as below:
First, I use application method Data.java to save data.
It contain the data:
private ArrayList<String> data = new ArrayList<String>();
public int getsize() {
return this.data.size();
}
public String getdata(int i) {
return this.data.get(i);
}
public void adddata(String s) {
return this.data.add(s);
}
My AActivity class onCreate as below:
Data d = (Data)this.getApplication();
String test = new String[d.getsize()];
for(i = 0; i < d.getsize(); i++) {
test[i] = d.getdata(i);
}
//to show in list
DataAdapter = new DataAdapter (this, test);
setListAdapter(DataAdapter);
And when button is click, startActivity the BActivity class.
In BActivity class, the code as below:
Data d = (Data)this.getApplication();
d.adddata("newdata");
finish();
And AActivity class onResume() as below:
#Override
public void onResume(){
super.onResume();
this.DataAdapter.notifyDataSetChanged();
}
But why the list is not update?
I confirm the data has be save.
My DataAdapter:
public DataAdapter(Context ctxt, String[] d) {
this.data = new String[d.length];
myInflater = LayoutInflater.from(ctxt);
int i;
for(i = 0; i < d.length; i++) {
data[i] = d[i];
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewTag viewTag;
if(convertView == null) {
convertView = myInflater.inflate(R.layout.row_bookmark_list, null);
viewTag = new ViewTag((TextView)convertView.findViewById(R.id.tv));
convertView.setTag(viewTag);
}
else {
viewTag = (ViewTag) convertView.getTag();
}
viewTag.tv.setText(data[position]);
}
class ViewTag {
TextView tv;
public ViewTag(TextView t) {
this.tv = t;
}
}
Add your new data directly to the adapter not to 'd'. The adapter keeps its own internal data which means that whatever changes you apply to your 'd' has no impact on the adapter.
For example:
List<String> itemsList = new ArrayList<String>();
ArrayAdapter aa = new ArrayAdapter(..., itemsList);
...
itemsList.add("new item"); --> wrong!
aa.notifyDataSetChanged(); --> nothing changes, you wrongly added the item to itemsList
you have to deal directly with the adapter:
aa.add("new item"); --> correct
aa.notifyDataSetChanged(); --> the adapter will reflect the change
You can't access the notifyDataSetChanged as a static method
( thats what you are doing in your example ).
If you have a ListActivity: you have access to the method getListAdapter().
Thats the right reference to your dataset.
So in short:
getListAdapter().notifyDataSetChanged();
will do the trick. If you don't have a ListActivity then you will have to find your listview thru View.findViewById([id of listview]) and get the Adapter there.
Hope this helps a bit :-)
I think your problem is that your DataAdapter is referenced to the array test, but test never changes. Referencing data to the DataAdapter instead of test should work.
OK, after looking at the Adapter code it will not work. Why are you copying your data? The adapter will never notice a change in the data element, because it is only working with a copy of that element at construction time. If copying the data is necessary, you should make sure the adapter updates its content, too.

Categories

Resources