Sum method called multiple times in getview - android

I have a method that add days in the date of the listview, the problem is when I scroll down and up again the values are changed, I have 2 kinds of date, so the method has to be called when the second kind appears in the list, but how can I use the method once so it doesn't keep adding each time I scroll it?
public class FaturasAdapter extends ArrayAdapter<Faturas> {
private Activity activity;
private LayoutInflater inflater;
private List<Faturas> faturasItens;
private Ferramentas mFerramentas;
private String entrada;
private String parcela = "";
private Map<Integer, Integer> intervaloMap;
private String data ="";
public FaturasAdapter(Activity activity, RealmList<Faturas> inItems) {
super(activity, R.layout.faturas_adapter, inItems);
this.activity = activity;
this.faturasItens = inItems;
this.mFerramentas = new Ferramentas();
this.intervaloMap = new HashMap<Integer, Integer>();
}
#Override
public int getCount() {
return faturasItens.size();
}
#Override
public Faturas getItem(int location) {
return faturasItens.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
final ViewHolder holder;
final Faturas mFaturas = faturasItens.get(position);
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
vi = inflater.inflate(R.layout.faturas_adapter, null);
holder = new ViewHolder();
holder.numero = (TextView) vi.findViewById(R.id.numero);
holder.intervalo = (TextView) vi.findViewById(R.id.intervalo);
holder.valor = (TextView) vi.findViewById(R.id.valor);
holder.data = (TextView) vi.findViewById(R.id.data);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
addIntervalo(mFaturas.getIntervalo(), mFaturas.getTipo());
data = mFerramentas.dataText(intervaloMap.get(mFaturas.getTipo()));
holder.intervalo.setText(String.valueOf(mFaturas.getIntervalo()));
if (mFaturas.getTipo() == Faturas.intervaloConstanteEntrada) {
entrada = "ENT - ";
holder.numero.setText(entrada + mFaturas.getOrder() + "/" + mFaturas.getQtParcelasEntrada());
holder.valor.setText(String.valueOf(mFaturas.getValor()) + " ");
} else {
parcela = "PAR - ";
holder.numero.setText(parcela + mFaturas.getOrder() + "/" + mFaturas.getQtParcela());
holder.valor.setText(String.valueOf(mFaturas.getValor()) + " ");
}
holder.data.setText(data);
return vi;
}
private void addIntervalo(int intervalo, int tipo) {
int intervaloSum = intervalo;
if (!intervaloMap.isEmpty()) {
if (intervaloMap.get(tipo) != null)
intervaloSum += intervaloMap.get(tipo);
}
intervaloMap.put(tipo, intervaloSum);
}
public List<Faturas> getfaturasItens() {
return faturasItens;
}
public void setData(List<Faturas> fat) {
this.faturasItens.addAll(fat);
this.notifyDataSetChanged();
}
public class ViewHolder {
TextView numero;
TextView intervalo;
TextView data;
TextView valor;
}
}

As I said in my comment I don't see why do you need to call the addIntervalo() method in the getView() method. The problem with this is that getView() will be called a lot as the user uses the ListView so you'll end up adding the same data again and again.
From your code it seems you just show the data calculated with addIntervalo()(I'm assuming each item will present its data relative to the total that you calculate for that type that you calculate with addIntervalo()) so you could simply calculate in advance the values and then in getView() simply use that.
// in the constructor you get the data so calculate the values
// iterating over the data
public FaturasAdapter(Activity activity, RealmList<Faturas> inItems) {
super(activity, R.layout.faturas_adapter, inItems);
this.activity = activity;
this.faturasItens = inItems;
this.mFerramentas = new Ferramentas();
this.intervaloMap = new HashMap<Integer, Integer>();
foreach(Faturas f : inItems) {
addIntervalo(f.getIntervalo(), f.getTipo());
}
}
You also have the setData() method where you update the data list so you also need to calculate the result of addIntervalo() for the new items that are about to be added to the adapter:
public void setData(List<Faturas> fat) {
// because you're adding the fat list to the current set of items
// simply calculate addIntervalo() for them to add their count to the total
foreach(Faturas f : fat) {
addIntervalo(f.getIntervalo(), f.getTipo());
}
this.faturasItens.addAll(fat);
this.notifyDataSetChanged();
}
In getView() remove the line:
addIntervalo(mFaturas.getIntervalo(), mFaturas.getTipo());
as you already calculated the values.

Oh, it's problem for base android list's widget to change view. You should know, that ListView and RecycleView caching and invalidating views per scrolling! So your views will be changed to default type!
RecycleView has solution, it's using several type from method getItemType(). But you work with ListView. Anyway! Better solution it's use special list widget which supports custom views and changing that views in anytime. For this task use LinkedListView!

Related

Change the visibility of a View while repeating data

I am populating OrderHistory by retrieving data from Server in my app. Here I need to populate listitem depends on OrderId. If OrderId repeats I need to hide the LinearLayout which is marked in green in screenshot. Otherwise the Layout has to be usual view.Please help me.
MyAdapter Class:
public class MyOrderAdapter extends RecyclerView.Adapter<MyOrderAdapter.ViewHolder> {
Context mContext;
List<CartRes> mOrderList = new ArrayList<>();
private ImageLoader imageLoader;
public MyOrderAdapter(Context context, List<CartRes> orderList) {
mContext = context;
mOrderList = orderList;
Log.e("Json Adapter", "" + mOrderList);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_order_history, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cartResOrder = mOrderList.get(position);
imageLoader = CustomVolleyRequest.getInstance(mContext).getImageLoader();
String IMAGE_URL = "http://" + Config.IMAGE_URL + holder.cartResOrder.ORDER_IMAGE;
Log.e("Image URL", IMAGE_URL + " " + holder.cartResOrder.ORDER_IMAGE);
imageLoader.get(IMAGE_URL, ImageLoader.getImageListener(holder.orderImage, 0, 0));
holder.orderImage.setImageUrl(IMAGE_URL, imageLoader);
holder.txtOrderId.setText(holder.cartResOrder.ORDER_ID);
holder.txtOrderProduct.setText(holder.cartResOrder.ORDER_PRODUCT);
holder.txtorderedDate.setText(holder.cartResOrder.ORDER_DATE);
holder.txtDeliveredDate.setText(holder.cartResOrder.ORDER_DELIVERY_DATE);
}
#Override
public int getItemCount() {
return mOrderList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView txtOrderId, txtOrderProduct, txtorderedDate, txtDeliveredDate;
Button butDetail, butRemove;
NetworkImageView orderImage;
CartRes cartResOrder;
public ViewHolder(View itemView) {
super(itemView);
txtOrderId = (TextView) itemView.findViewById(R.id.orderId);
txtOrderProduct = (TextView) itemView.findViewById(R.id.orderProduct);
txtorderedDate = (TextView) itemView.findViewById(R.id.orderedDate);
txtDeliveredDate = (TextView) itemView.findViewById(R.id.orderDeliveredDate);
butDetail = (Button) itemView.findViewById(R.id.orderViewDetail);
butRemove = (Button) itemView.findViewById(R.id.orderRemove);
orderImage = (NetworkImageView) itemView.findViewById(R.id.OrderproductImage);
}
}
}
UPDATE:
public void onBindViewHolder(ViewHolder holder, int position) {
holder.cartResOrder = mOrderList.get(position);
imageLoader = CustomVolleyRequest.getInstance(mContext).getImageLoader();
String IMAGE_URL = "http://" + Config.IMAGE_URL + holder.cartResOrder.ORDER_IMAGE;
Log.e("Image URL", IMAGE_URL + " " + holder.cartResOrder.ORDER_IMAGE);
imageLoader.get(IMAGE_URL, ImageLoader.getImageListener(holder.orderImage, 0, 0));
holder.orderImage.setImageUrl(IMAGE_URL, imageLoader);
holder.txtOrderId.setText(holder.cartResOrder.ORDER_ID);
holder.txtOrderProduct.setText(holder.cartResOrder.ORDER_PRODUCT);
holder.txtorderedDate.setText(holder.cartResOrder.ORDER_DATE);
holder.txtDeliveredDate.setText(holder.cartResOrder.ORDER_DELIVERY_DATE);
if (position > 0 && mOrderList.get(position).ORDER_ID == mOrderList.get(position - 1).ORDER_ID) {
//make sure it is not the first one, and make sure it has the same ID as previous.
holder.OrderLinear.setVisibility(View.GONE); //hide it, you need to set the reference first.
holder.txtOrderId.setVisibility(View.GONE);
}
}
One way you could do it:
Have a new holder variable that refers to your LinearLayout you want to hide.
In your onBindViewHolder()
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
//setup everything else above...
if (position > 0 && mOrderList.get(position).ORDER_ID == mOrderList.get(position - 1).ORDER_ID){
//make sure it is not the first one, and make sure it has the same ID as previous.
holder.thelinearlayout.setVisibility(View.GONE); //hide it, you need to set the reference first.
}else holder.thelinearlayout.setVisibility(View.VISIBLE);
//if somehow order gets changed.(e.g. previous row is deleted).
}
EDIT:
I'm assuming that the data inside is sorted by ORDER_ID, so there won't be a case where there are two elements with the same ORDER_ID that is not next to each other.
You might want to sort them based on ORDER_ID before passing the list into adapter.
EDIT2:
Added else condition as suggested in the comment.
The screenshot does not tell that but if your view is RecyclerView or ListView then I'd preprocess the data prior feeding it to the adapter (i.e. by wrapping your model into another class with additional attributes).
Alternatively you can try checking previous row (by fetching it from your data source or adapter) while populating current one and adjust the view
maybe just add field boolean repeatOrderId to your CartRes class and in constructor do some for loop and flag all items? you may check also in runtime, but you have pretty fixed list, preparing in construtor this flag is better for performance
for(int i=0; i<mOrderList.getCount(); i++){
CartRes cr = mOrderList.get(i);
cr.repeatOrderId=true;
for(int j=0; j<i; j++){
if(cr.ORDER_ID==mOrderList.get(j).ORDER_ID){
cr.repeatOrderId=false; //default true
break;
}
}
}
then inside onBindViewHolder check this flag and setVisibility(cr.repeatOrderId); for desired layout

ArrayAdapter strange behaviour with id when items's height exceed Listview height

I'm facing a strange behaviour using an ArrayAdapter.
When the number of listview item exceed the height of the listView (say after item 8), the next item get the id 0 instead the id 9.
In my opinion this type of issue was explained here with the convertView, but i use it in the same way (i think).
The following code is my ArrayAdapter.
public class StepsAdapter extends ArrayAdapter<String> {
Context context;
List<String> steps;
public StepsAdapter(Context context, int resourceId, List<String> steps) {
super(context, resourceId, steps);
this.context = context;
}
private class ViewHolder {
EditText stepValue;
ImageView removeStep;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
final String step = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row_step, null);
holder = new ViewHolder();
holder.stepValue = (EditText) convertView.findViewById(R.id.stepEdit);
holder.removeStep = (ImageView) convertView.findViewById(R.id.removeStep);
holder.stepValue.setText(step);
holder.removeStep.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context,"* Remove id step " + position, Toast.LENGTH_LONG).show();
steps.remove(position);
notifyDataSetChanged();
}
});
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
return convertView;
}
}
Then my main activity where i get existing data and put it in my listView, the add button and the save button.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_game);
mContext = getApplicationContext();
steps = new ArrayList<String>();
stepsAdapter = new StepsAdapter(mContext,R.layout.row_step,steps);
Gson gson = new GsonBuilder().create();
game = gson.fromJson(gameJson, Games.class);
/*
* Settings values
*/
gameNameValue.setText(game.getName());
gameBackgroundPreview.setBackgroundColor(game.getColor());
colorSelected = game.getColor();
for(int i = 0; i < game.getSteps().size() ; i++){
//steps.add(game.getSteps().get(i).toString());
//notifyDataSetChanged();
stepsAdapter.add(game.getSteps().get(i).toString());
}
final ListView listSteps = (ListView) findViewById(R.id.listViewSteps);
listSteps.setAdapter(stepsAdapter);
gameNameValue.setText(gameName);
addSteps.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stepsId = steps.size();
Toast.makeText(getApplicationContext(), "addSteps : " + stepsId, Toast.LENGTH_LONG).show();
stepsAdapter.insert("newstep", stepsId);
}
});
buttonSaveGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String valueEditGameName = gameNameValue.getText().toString();
int valueColorBackaground = colorSelected;
String picture = "testPic";
for(int i=0; i < listSteps.getChildCount(); i++) {
LinearLayout rowLayout = (LinearLayout) listSteps.getChildAt(i);
//Log.e(TAG, ">> :) layout >>" + listSteps.getChildAt(i).getClass().getName());
EditText editRow = (EditText) rowLayout.getChildAt(0);
stepsValues.add(editRow.getText().toString());
//Log.e(TAG, ">> :) inside layout >>" + editRow.getText().toString());
}
if(valueEditGameName.trim().length() > 0 && picture.trim().length() >0 ){
Games game = new Games(valueEditGameName,valueColorBackaground,picture,stepsValues);
String goToSave = game.createJson();
Log.e(TAG, ">>Saved>>" + goToSave);
final CkdFile file = new CkdFile();
String saved = file.writeToSDFile(game.getName(), goToSave);
Toast.makeText(mContext, saved, Toast.LENGTH_LONG).show();
Intent backToMain = new Intent(mContext,MainActivity.class);
startActivity(backToMain);
} else {
Toast.makeText(mContext, "Fill all texts", Toast.LENGTH_LONG).show();
}
}
});
}
I try to add items in 2 different ways :
add item through : List steps
add item through : StepsAdapter stepsAdapter
Both give me same behaviour.
If someone has a clue to help understanding what i'm doing wrong with my implementation of ListView/ArrayAdapter.
Thanks in advance !
EDIT 1 :
After pushing some logs everywere, it understand the strange behaviour :
My adapter have only 6 slots (the limit came from the size of the listview in layout), and when my arraylist have more than 6 items, the getView select items only between 0 and 5.
I'm searching now a way to get the position in ArrayList and not the position in arrayadapter.
I faced same issue recently. Add following overrides to Adapter:
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
I found a simple xml "trick" to avoid this behaviour : i set a biger height to listView.
<ListView
android:layout_width="match_parent"
android:layout_height="1000dp"
android:layout_gravity="center_horizontal"
android:id="#+id/listViewSteps"
android:layout_margin="10dp">
</ListView>
It's not really resolve but a take it ...

Refreshing a ListView's adapter from inside an AsyncTask without duplicates

I have a ListView and obviously an adapter the uses a List<T> object.
I added a button that is supposed to refresh the listview (= re-query the database and recreate the ListView).
All of the above (from querying the db to setting the adapter) happens inside an AsyncTask.
Update Button Code
mRefreshButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setClickable(false);
new GetScheduleTask().execute((Void[]) null); //Basically, execute it again.
}
});
AsyncTask (I deleted some unnecessary code)
private class GetScheduleTask extends AsyncTask<Void, Void, List<Object[]>> {
#Override
protected List<Object[]> doInBackground(Void... params) {
SQLiteDatabase db = SchooLauncherDbHelper.getInstance(getActivity()).getReadableDatabase();
//TODO test repetition
String sql = "LONG A** SQL HERE";
Cursor c = db.rawQuery(sql, new String[] {String.valueOf(cal.getTimeInMillis()), String.valueOf(cal.getTimeInMillis()),
String.valueOf(cal.getTimeInMillis()), String.valueOf(cal.get(Calendar.MONTH))});
while(c.moveToNext()) {
......................
mEventList.add(new Object[] {new Class(...), new Subject(...)});
}
}
db.close();
return mEventList;
}
#Override
protected void onPostExecute(List<Object[]> result) {
mScheduleListView = (ListView) view
.findViewById(R.id.mScheduleListView);
TextView myTv = new TextView(getActivity());
myTv.setText("No Results");
mScheduleListView.setEmptyView(myTv);
mScheduleEventAdapter = new ScheduleEventAdapter(getActivity(),
R.layout.schedule_item_layout, mEventList);
mScheduleListView.setAdapter(mScheduleEventAdapter);
if(!mImageView.isClickable())
mImageView.setClickable(true);
}
}
ScheduleEventAdapter
public class ScheduleEventAdapter extends ArrayAdapter<Object[]>{
private Context context;
private int layoutResourceId;
private List<Object[]> data = null;
private View row = null;
private LayoutInflater inflater;
private Subject mSubject;
private Event mEvent;
private String mEventStartTime, mEventEndTime;
public ScheduleEventAdapter(Context context, int layoutResourceId, List<Object[]> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
row = convertView;
if(row == null) {
inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(this.layoutResourceId, parent, false);
}
mSubject = (Subject) data.get(position)[1];
mEvent = (Event) data.get(position)[0];
((ImageView) row.findViewById(R.id.subjecticon)).setImageResource(mSubject.icon);
((TextView) row.findViewById(R.id.schedule_event_subject_name)).setText(mSubject.name);
((TextView) row.findViewById(R.id.schedule_event_title)).setText(mEvent.mEventTitle);
((TextView) row.findViewById(R.id.schedule_event_location)).setText(((Class)mEvent).mClassLocation);
this.mEventStartTime = ((int) mEvent.mEventStartTime / (1000*60*60)) + ":" + ((int) (((mEvent.mEventStartTime / (1000*60)) % 60)));
this.mEventEndTime = ((int) mEvent.mEventEndTime / (1000*60*60)) + ":" + ((int) (((mEvent.mEventEndTime / (1000*60)) % 60)));
((TextView) row.findViewById(R.id.schedule_event_time)).setText(this.mEventStartTime + " - " + this.mEventEndTime);
return row;
}
}
The Problem
The problem is that the button works, but instead of re-creating the list, duplicates are being shown.
As you can see, new items are being added mEventList, even the ones that already show.
I could use an if statement with the .contains() method of the list to determine whether an object needs to be added to the list or not, but the problem is, even though the contents of the objects may be the same, the pointers are different which I guess is why it also doesn't work (I tried).
I also tried resetting the adapter and playing with the data and .notifyDataSetChanged() but it didn't work.
The only solution I could think of is to compare each field of each object inside the array, but that sounds too much like a performance-hit to me.
If so, what would be the most efficient and correct way to fix this problem?

Android :I can't get value in dialog while binding dynamic textviews through base adapter class

I got exception in dialog while binding dynamic textviews through base adapter class
i can get the dialog box but it doesnot bind the textview value hell.. plz help me.. wat i did wrong :)
Train_Origin_Destination.java
public void loadAutocomplete1(String strCmdTrain) {
c.moveToFirst();
if (c.isAfterLast() == false) {
do {
listFrom1 = new ArrayList<String>(Arrays.asList(strComments));
listTo1 = new ArrayList<String>(Arrays.asList(strComments));
listFrom1.removeAll(Collections.singleton(null));
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_Start, "Hello");
listData.add(map);
Log.e("map", map.toString());
Log.e("list4", listData.toString());
customAdapter = new MyCustomAdapter2(
Train_Origin_Destination.this, listData);
lvTrainTime1.setAdapter(customAdapter);
} while (c.moveToNext());
}
onButtonClick Event
public void onClick(View arg0) {
Log.d("Dialog", "Dialog");
dialog = new Dialog(context1);
//dialog.setContentView(R.layout.traintimings_dialog);
//dialog.getWindow().getAttributes().windowAnimations = R.style.Animations_SmileWindow;
dialog.setTitle("Train Timings");
//dialog.setContentView(R.id.lvTrainTimings1);
if (chkSunday.isChecked()) {
if (Area_Index < Area_Index1) {
Log.d("Sunday", "Sunday");
} else if (Area_Index > Area_Index1) {
Log.d("SundayReverse", "SundayReverse");
}
} else {
if (Area_Index < Area_Index1) {
Log.d("Normal", "Normal");
if (strSpSelectedItem.contentEquals("Beach - Tambaram")) {
int id = Area_Index + 1;
int id1 = Area_Index1 + 1;
/*
* strCmdTrainFrom =
* "Beach_Thirumalpur_WeekD ays where _id='" + id +
* "' or _id='" + id1 + "'";
*/
strCmdTrainFrom = "Beach_Thirumalpur_WeekDays where _id='"
+ id + "'";
loadAutocomplete1(strCmdTrainFrom);
}
} else if (Area_Index > Area_Index1) {
Log.d("NormalReverse", "NormalReverse");
}
}
Log.d("DialogEndB4", listData.toString());
dialog.show();
Log.d("DialogEnd", "DialogEnd");
}
MyCustomAdapter2.java
public class MyCustomAdapter2 extends BaseAdapter {
private String[] strKeys;
private ArrayList<HashMap<String, String>> alData;
private Context context;
TextView txtBusNo, txtBusVia, txtBusServiceType, txtBusJourneyTime;
TextView[] tvStart;
ListView lvTrainTime1;
View rowView2;
public MyCustomAdapter2(Context context,
ArrayList<HashMap<String, String>> listData) {
super();
Log.d("Custom", "Custom");
this.alData = listData;
this.context = context;
Log.d("alData", alData.toString());
Log.d("Custom1", "Custom1");
}
public int getCount() {
// TODO Auto-generated method stub
Log.d("alData.size()", String.valueOf(alData.size()));
return alData.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Log.d("View", "View");
rowView2 = convertView;
if (rowView2 == null) {
Log.d("View1", "View1");
Train_Origin_Destination trDetails = new Train_Origin_Destination();
// Inflate the layout, list_view.xml, in each row.
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(context.LAYOUT_INFLATER_SERVICE);
Log.d("View2", "View2");
rowView2 = inflater
.inflate(R.layout.textview_autofrom, null, false);
}
txtBusNo = (TextView) rowView2.findViewById(R.id.idTvAutoFrom1);
Log.d("View3", "View3");
HashMap<String, String> hashmap = new HashMap<String, String>();
txtBusNo.setText("Bus No : Hello");
Log.d("View30", "View30");
Log.d("View5", String.valueOf(rowView2));
} else {
}
return rowView2;
}
Well what you do is add lvTrainTime to the scr ScrollView than use it as a content view for the dialog. Maybe what you want to do is setContentView(scr);? If you do it this way scr will play the role of a container of the view. So basically you need to set the container as a content view.
EDIT - clarifications:
What I meant was that in your loadAutocomplete1 method you create a ScrollView scr = new ScrollView(this);. Later in the same method, after the loop, you add a view to that scroll view - scr.addView(lvTrainTime); and then set the content view of the dialog to be the mentioned view - dialog.setContentView(lvTrainTime);. You cant do that because scr and dialog are different controls and one view (lvTrainTime) can't have two parents.
So, instead of setting the content view to be that view - lvTrainTime - I meant that you should set it's parent(container) as a content view. By the time I answered I thought it was scr that should be set as content view but I just saw that you actually put the scr in a tableLayout - tablelayout.addView(scr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, 50));. So your current situation is that lvTrainTime is inside scr and scr is inside tableLayout. So try dialog.setContentView(tableLayout); instead. In addition I am not sure what happens when you set the content view of the dialog twice so maybe you should try without dialog.setContentView(R.layout.traintimings_dialog); too.

Android: Showing the listview with custom adapter - filter the arraylist

I have a peculiar problem. I am parsing a restaurant's menu card. They have it in english and in german. I have a class FoodItem as :
public class FoodItem {
private int foodClass;
private String foodType;
private String foodName;
private String foodCost;
private String hauptBeilage;
private String salat;
}
Now, I have an arraylist of fooditems downloaded using Jsoup. I separate the german and english menu using the String foodType.
I want to list german menu at the start. But, I get the english menu appended to the list as well. How should I tackle this?
My downloadThread (Jsoup) is :
public void run()
{
Log.i("downloadThread", "Inside run() - Starting getFoodItems");
getDailyGerman();
getDailyEnglish();
//Sending a message through handler here
}
In my activity, I have:
handler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
foodItemAdapter.notifyDataSetChanged();
}
};
If I send a message through handler after getDailyGerman(); then i get a illegalstateexception saying the content of the adapter has changed, but the listview is not updated.
My Adapter code :
public FoodItemAdapter(Context context, int textViewResourceId, ArrayList<FoodItem> FoodItemArg) {
super(context, textViewResourceId, FoodItemArg);
FoodItemAdapter.foodItems = FoodItemArg;
this.setNotifyOnChange(false);
// if(FoodItemAdapter.foodItems == null)
// Log.i("Adapter", "Problem Inside Adapter Constructor");
}
//=========================public methods============================
public static ArrayList<FoodItem> getDailyEnglishFoodItems()
{
ArrayList<FoodItem> returnList = new ArrayList<FoodItem>();
for(FoodItem eachItem : FoodItemAdapter.foodItems)
{
if(eachItem.getFoodClass() == 1)
{
Log.i("Adapter" , "Adding English Daily Food : " + eachItem.getFoodName());
returnList.add(eachItem);
}
}
return returnList;
}
public static ArrayList<FoodItem> getDailyGermanFoodItems()
{
ArrayList<FoodItem> returnList = new ArrayList<FoodItem>();
for(FoodItem eachItem : FoodItemAdapter.foodItems)
{
if(eachItem.getFoodClass() == 2)
{
Log.i("Adapter" , "Adding German Daily Food : " + eachItem.getFoodName());
returnList.add(eachItem);
}
}
return returnList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
/*
* Describes each view in the list view.
* Get the question and find the question text, timestamp and the votes.
* Show them in the textview which is a part of the listview.
*/
View v = convertView;
FoodItem foodItem =(FoodItem) FoodItemAdapter.foodItems.get(position);
if(foodItem == null)
{
Log.i("Adapter", "Null Food Item");
}
int colorPos = 0;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.fooditem_row, null);
colorPos = position % colors.length;
}
Please help as I am stuck at this point for 3 days. Thanks.
I had the same issue once I added the items and called
notifyDataSetChanged() in the UI
thread issue solved
From What I understand of your question, you want to have the English items at the top of the list then the German Items. you can do that using Collection.sort method and Using a specific comparator for the task in hand.
For example:
final List<FoodItem> combinedList = getDailyGermanFoodItems();
combinedList.addAll(getDailyEnglishFoodItems());
Collections.sort(compinedList, new FoodItemComparator());
//then you call the handler to update the adapter and the listView
handler.post(new Runnable(){
public void run(){
FoodItemAdapter adapter = new FoodItemAdapter(activity.this, layout, combinedList);
listView.setAdapter(adapter);
}});
where FoodItemComparator:
public class FoodItemComparatorimplements Comparator<FoodItem>{
public int compare(FoodItem item1, item2) {
String foodType1 = item1.getFoodType();
String foodType2 = item2.getFoodType();
if (foodType1.equals(foodType2))
return 0;
if (foodType1.equals("English"))
return 1;
if (foodType2.equals("English))
return -1;
return foodType1.compareTo(foodType2);
}
}
Assuming foodType Value is guaranteed to be German/English only.
Also you will have to have a getter funcion inside your FoodItem Class so the comparator can access it:
Class FoodItem
.......
public String getFoodType(){
return foodType;
}
EDIT
If you want to display each one alone , then store the two lists inside your activity object, then when user select a language (english / german):
FoodItemAdapter adapter = new FoodItemAdapter(activity.this, layout, germanList);
listView.setAdapter(adapter);

Categories

Resources