Listview displaying only last item - android

I have written a code to display json items into listview , when i debug the code i can see the data properly , when i am setting the list to the listview i am only seeing the last item
Code i tried :
try {
foodintervallist.clear();
final String result = response.body().string();
JSONObject jsonObject = new JSONObject(result);
String data = jsonObject.getString("data");
JSONArray foodintervalarray = new JSONArray(data);
HashMap<String, String> menuMap =
new HashMap<String, String>();
for (int j = 0; j < foodintervalarray.length(); j++) {
String key1 = "";
JSONObject jsonObject1 =
foodintervalarray.getJSONObject(j);
final String food_interval =
jsonObject1.getString(FOOD_INTERVAL);
if (jsonObject1.isNull(ITEM_NAME)) {
item_name = "";
} else {
item_name = jsonObject1.getString(ITEM_NAME);
}
if (!menuMap.containsKey(food_interval)) {
menuMap.put(food_interval, item_name);
} else {
String key = menuMap.get(food_interval);
key1=key+","+item_name;
menuMap.put(food_interval, key1);
}
runOnUiThread(new Runnable() {
#Override
public void run() {
foodintervallist.add(menuMap);
listViewAdapter = new ListViewAdapter(Diet_Order_Activity_New.this, foodintervallist);
listView.setAdapter(listViewAdapter);
listViewAdapter.notifyDataSetChanged();
}
});
}
My BaseAdapter class
#Override
public View getView(int position, View convertView, ViewGroup parent) {
inflater = (LayoutInflater)
activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.table_row, parent,
false);
resultp = fooditervallist.get(position);
txtFoodInterval = (TextView)
itemView.findViewById(R.id.foodInterval);
txtFoodItem = (TextView) itemView.findViewById(R.id.foodItems);
for (Map.Entry<String, String> entry : resultp.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
txtFoodInterval.setText(key);
Toast.makeText(activity, "" + key, Toast.LENGTH_LONG).show();
txtFoodItem.setText(value);
// do what you have to do here
// In your case, an other loop.
}
return itemView;
}
I am declaring the foodintervallist globally in my main activity class and also the listviewadapter i am initializing inside oncreate method
I am getting the data inside my arraylist , but i am able to display only the last item , what to do ?
Thanx

I would recommend to check your implementation of Adapter's getCount(). As it is not provided how it looks, I would looked there...
it should be like:
public int getCount (){ return fooditervallist.get(0).size() }
As you provide a list with only one item. Also I see there some issues in getView() :
fooditervallist.get(position); --> don't use position there, your list has always only one item therefore use 0 instead otherwise you'll get null pointer
your for loop is setting the txtFoodInterval and txtFoodItem with the all values in the Map.Set which might result in all list items having the same value ... instead of for loop you should use a "position" parameter here which is not possible with HashMap as order is not predicable. Use LinkedHashMap instead to have correct order and logic needs to be adjusted
Nevertheless I would implement it differently:
JSON parsing - I would create a new object model for holding the data
class FoodItem { int interval; String name; // getters and setters
here }
I would put these items in the list you put your map
In adapter you can then use this object quite easily like without any for loop like:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
inflater = (LayoutInflater)
activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.table_row, parent, false);
FoodItem item = fooditervallist.get(position);
txtFoodInterval = (TextView) itemView.findViewById(R.id.foodInterval);
txtFoodItem = (TextView) itemView.findViewById(R.id.foodItems);
txtFoodInterval.setText(item.interval) ;
txtFoodItem.setText(item.name);
return itemView;
}
Also I would recommend to have a look on Retrofit library. It will make your life easier...

put your Hashmap inside the for loop. Because when you use globally the data will be overrided and you get only last item.

Put the below code outside the loop // set adapter outside the loop
listViewAdapter = new ListViewAdapter(Diet_Order_Activity_New.this,foodintervallist);
listView.setAdapter(listViewAdapter);
listViewAdapter.notifyDataSetChanged();

Related

Add Image in listView using image from url Picasso crash in android

Bonjour
I have spent days and night looking for an answer suitable to my case
can you help please
Here is the code I am using
anytime I add the ligne with Picasso, the program crashes
It works fine with static images from drawable
I just want to display the text with the image that corresponds
public void Afficher_les_vues(String url_in) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url_in)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
if (response.isSuccessful()) {
myResponse = response.body().string();
Annonces.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
JSONObject reader = new JSONObject(myResponse);
JSONArray eglises = reader.getJSONArray("Annonces_adv");
arrayList.clear();
for (int i = 0; i < eglises.length(); i++) {
JSONObject eglise = eglises.getJSONObject(i);
String titre = eglise.getString(titret);
String description = eglise.getString(descriptionet);
int ref = Integer.parseInt(eglise.getString(reft));
String image = eglise.getString(imaget);
String url_image = eglise.getString(imaget);
HashMap<String, String> data = new HashMap<>();
data.put(titret, titre);
data.put(descriptionet, description);
data.put(reft, String.valueOf(ref));
data.put(imaget, image);
data.put(url_imaget, url_image);
arrayList.add(data);
ImageView imageViewlogo = findViewById(R.id.imageViewLogoNews);
//Picasso.get().load(url_image).into(imageViewlogo);
//new GetImageFromUrl(imageViewlogo).execute(url_image);
ListAdapter adapter = new SimpleAdapter(Annonces.this, arrayList, R.layout.listview_layout
, new String[]{titret, descriptionet, reft, url_imaget}, new int[]{R.id.titre_de, R.id.description_de,
R.id.reference, R.id.url_image});
lv.setAdapter(adapter);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
When I use Picasso to display and image in a simple ImageView not in a listView, it works fine
Thank you in advance
I work with android studio
Blessings
The main things you need to fix are not creating the adapter every loop instance and not accessing row views (the ImageView) from outside the adapter.
1. Do not make the adapter inside the loop
You should build the array of data to display first, then after the loop that builds the array create the adapter and set it on the ListView. When you have a custom adapter, it is helpful to use a small data class to hold the data you need to show in each row (see RowData later in the answer)
arrayList.clear(); // ArrayList<RowData>()
for (int i = 0; i < eglises.length(); i++) {
JSONObject eglise = eglises.getJSONObject(i);
String titre = eglise.getString(titret);
String description = eglise.getString(descriptionet);
int ref = Integer.parseInt(eglise.getString(reft));
String url_image = eglise.getString(imaget);
RowData data = new RowData(titre, description, String.valueOf(ref), url_image);
arrayList.add(data);
}
// You CANNOT access row view here - in this context findViewById searches the main
// view heirarchy, and will not find views in your ListView rows
// Make the adapter *AFTER* the loop where you fill the array
// you will need to make your own custom adapter to load the image
ListAdapter adapter = new CustomAdapter(Annonces.this, R.layout.listview_layout, arrayList);
lv.setAdapter(adapter);
2. Do not attempt to access row views outside the adapter
Your row views should only be accessed inside getView in your adapter itself. This is where you should load the image. If you were using a standard adapter before, you will need to implement your own custom adapter to do this. There are instructions for how to do that here. The adapter below takes an ArrayList of RowData items and uses that to populate each row.
public class CustomAdapter extends ArrayAdapter<RowData> {
private Context mContext;
private int mResource;
public MainAdapter(#NonNull Context context, int resource, #NonNull ArrayList<RowData> objects) {
super(context, resource, objects);
mContext=context;
mResource=resource;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
if( convertView == null ) {
LayoutInflater inflater = LayoutInflater.from(mContext);
convertView = inflater.inflate(mResource, parent, false);
}
// Get the views for this row (these must be in the
// layout xml you passed in to the adapter constructor)
TextView title = convertView.findViewById(R.id.titre_de);
TextView description = convertView.findViewById(R.id.description_de);
TextView reference = convertView.findViewById(R.id.reference);
ImageView imageViewlogo = convertView.findViewById(R.id.imageViewLogoNews);
// Get the RowData class for this row
RowData data = getItem(position);
// Set the text fields
title.setText(data.title);
description.setText(data.description);
reference.setText(data.reference);
// Start Picasso loading into the ImageView for this row
Picasso.get().load(data.url).into(imageViewlogo);
return convertView;
}
}
Make a small data class
When you have a custom adapter it is useful to make a custom data class that holds the data you want to show in each row. This avoids the possible errors in missing keys etc... you can get with a plain old map or passing in multiple lists.
public class RowData {
final String title;
final String description;
final String reference;
final String url;
RowData(String title, String desc, String ref, String url) {
this.title = title;
this.description = desc;
this.reference = ref;
this.url = url;
}
}

Android : get the view position by a <key,value> pair

In my app application i have an API that parsing JSON updating 500 rows is the list view. In a row I have id,name,number and status. Through the pushnotification am getting an id out of the 500 and I want update the status of that id having row.
Am using getter/setter method here so if getting the view position i can update the row.
This is the way am parsing
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject c = jsonArray.getJSONObject(i);
String phone = c.getString("phone");
String subDistributorStatus = c.getString("status");
String name = c.getString("firstName");
subDistributerId = c.getString("subDistributerId");
SubdistributorItem item = new SubdistributorItem();
item.setSubDistributorName(name);
item.setSubDistributorNumber(phone);
item.setSubDistributorStatus(subDistributorStatus);
item.setSubDistributorId(subDistributerId);
}
This is the way am updating single row
SubdistributorItem subdistributorItem = subdistributorItemList.get(Integer.parseInt(getFromPreference("Sub_position")));
String phone= subdistributorItem.getSubDistributorNumber();
String id= subdistributorItem.getSubDistributorId();
String status= subdistributorItem.getSubDistributorStat
Here am getting the position by clicking the view.
Now if i get one of the id in the row is there any chance to get the position in the view.
I tried HashMap.
**HashMap newmap = new HashMap(); // in global
newmap.put(subDistributerId,i); // in loop
Log.e("Tag ","hash map positon "+ newmap.get(43)); // in onResume**
But failed.
can any please help to get the position of the row ,if get id of the row.
You can use ArrayList along with the getter/setter class. You also have to extend the BaseAdapter class to get the string values of a particular position and map it to the view.
You can check the following example --
The below code will loop through the JSON and set the values using Setter methods and then it will add them to the ArrayList.
ArrayList<SubdistributorItem> listitem = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject c = jsonArray.getJSONObject(i);
String phone = c.getString("phone");
String subDistributorStatus = c.getString("status");
String name = c.getString("firstName");
subDistributerId = c.getString("subDistributerId");
SubdistributorItem item = new SubdistributorItem();
item.setSubDistributorName(name);
item.setSubDistributorNumber(phone);
item.setSubDistributorStatus(subDistributorStatus);
item.setSubDistributorId(subDistributerId);
listitem.add(item);
}
Then extend the BaseAdapter class to get the individual position and the values associated with it.
public class MyBaseAdapter extends BaseAdapter {
public Context ba_context;
public ArrayList<SubdistributorItem> listitem = new ArrayList<>();
public LayoutInflater inflater;
ListRowItem currentlistitem;
public MyBaseAdapter(Context ma_context, ArrayList<SubdistributorItem> ma_listitem) {
super();
this.ba_context = ma_context;
this.listitem = ma_listitem;
inflater = (LayoutInflater) ba_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return this.listitem.size();
}
#Override
public Object getItem(int position) {
return this.listitem.get(position);
}
#Override
public long getItemId(int position) {
return (long) position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.listview_item_layout, parent, false);
TextView carrier = (TextView) vi.findViewById(R.id.layout_textview1);
currentlistitem = listitem.get(position);
String str_carrier = currentlistitem.getCarrier();
carrier.setText(str_carrier);
return vi;
}
}
Finally call this class and set the adapter in the listview somewhere in your code as per your requirement.
baseAdapter = new MyBaseAdapter(context,listitem);
listView.setAdapter(baseAdapter);
Hope this helps!!

Update value on adapter

I wonder if there is any way to update an information of a single item within a listview. Basically I press the button inside the adapter and it makes a new request, the request will set this returns the value of the adapter. It is a system of "like".
I do not want to call the asynchronous method that gets the list, it takes much again. The code to get all the items in the database is this:
protected ArrayList<Feed> doInBackground(MyTaskParams... params) {
page = params[0].page;
mFilter = params[0].filter;
backgroundItems = new ArrayList<Feed>();
ParseQuery<ParseObject> query = ParseQuery.getQuery("FeedPost");
ParseObject parseObject;
try {
responseList = query.find();
for (int i = 0; i < responseList.size(); i++) {
parseObject = responseList.get(i);
backgroundItems.add(new Feed(parseObject.getObjectId(),
parseObject.getString("Title"),
parseObject.getString("Description"),
parseObject.getString("CompleteText"),
parseObject.getString("imageURL"),
parseObject.getString("Link_on_Site"),
parseObject.getNumber("like_count")));
}
} catch (ParseException e) {
exceptionToBeThrown = e;
}
return backgroundItems;
}
You didn't show your adapter code or your task for updating the like count in the database, so I'm going to assume you're using an AsyncTask. In the getView or bindView function is where you need to update it.
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if (convertView == null)
{
//inflate layout and initialize holder
}
else
{
holder = (ViewHolder)convertView.getTag();
}
//get item at position
MyItem item = getItem(position);
if (item != null)
{
holder.likeButton.setOnClickListener(
new OnClickListener()
{
#Override
public void onClick(View v)
{
//update database and set new value
IncrementLikeCountTask task = new IncrementLikeCountTask()
{
#Override
public void onPostExecute(int newValue)
{
item.setLikeCount(newValue);
notifyDataSetChanged();
}
}.execute(position);
}
}
);
}
return convertView;
}
So I assume you're persisting a list of Feed objects in your adapter.
What you need to do is after communicating with the server modify the like_count field of the appropriate Feed object in your adapter and call notifyDataSetChanged() on the adapter.
This will trigger a refresh of the ListView and render your list item with the updated value.

Android JSON input for setOnItemSelect

I am populating a ListView using remote JSON data in the following format:
{"nodes":[{"node":{"title":"Article#1","id":"4"}},{"node":{"title":"Article#2","id":"3"}}]}
My ListView is constructed with the following code:
ArrayList<String> articles = new ArrayList<String>();
try{
for(int i=0; i < data.length(); i++){
JSONObject dataObj = (JSONObject)data.get(i);
JSONObject record = dataObj.getJSONObject("node");
title = (record.getString("title"));
nid = (record.getString("nid"));
Log.i("FOUND", "title: " + title);
Log.i("FOUND", "nid: " + nid);
articles.add(title);
}
}catch(JSONException j){
Log.e("CHECK", "Attempting to read data returned from JSONReader: " + j.toString());
}
ListView articlesList = (ListView)findViewById(R.id.articlesList);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(ArticlesActivity.this, R.layout.article_item, R.id.articleItem, articles);
articlesList.setAdapter(adapter);
The entire process works and successfully lists my Article titles. But, I am trying to follow tutorials which will help me enable onSelectListeners on each list item. The ID element associated to each article title is all I need to remotely fetch the article content.
Is it possible to setup my ArrayList to contain both title and id data and use it to setup my dynamic OnSelectListener enabled ListView?
The proper way to do it is to create a class that will hold the article name and id and whatever info you need. In your custom adapter you setTag() method when you create the view.
Then in your onClickListener use getTag() method. Below I'll give you some code snipsetss hope they will help you.
public class Article{
private String name;
private String id;
public Article(String name, String id) {
this.name =name;
this.id = id;
}
public String getName() {
return name;
}
public String getID() {
return id;}
}
In you custom adapter class use setTag method when you create the view
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.group_list, null);
TextView title = (TextView) v.findViewById(R.id.group_title);
...//rest of my code
Article article = getItem(position);
title.setText(article.getName());
title.setTag(article);
v.setTag(article);
return v;
}
In your click listener
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Article article= (Article ) view.getTag();
String articleID= article.getID();
}
}

Android add items to arraylist using custom class

I'm trying to add items to an arraylist using this class template:
public class Template {
public String username;
public String email;
}
Here's the whole code:
public void JsonToArrayList(JSONArray myJsonArray) throws JSONException
{
ArrayList<Template> listItems = new ArrayList<Template>();
JSONObject jo = new JSONObject();
Template tem = new Template();
ListView lv = (ListView) findViewById(R.id.listView1);
for(int i = 0; i<myJsonArray.length(); i++)
{
jo = myJsonArray.getJSONObject(i);
tem.username = jo.getString("username");
tem.email = jo.getString("user_email");
listItems.add(tem);
Log.e("Ninja Archives", tem.username);
}
// This is the array adapter, it takes the context of the activity as a first // parameter, the type of list view as a second parameter and your array as a third parameter
ArrayAdapter<Template> arrayAdapter = new ArrayAdapter<Template>(this,android.R.layout.simple_list_item_1, listItems);
lv.setAdapter(arrayAdapter);
}
The problem is, instead of filling my listview with nice username and email strings, it's filling up with items like this:
com.android.ninjaarchives.
Template#40585690
I think somewhere along the line I have become lost, but I've been trying all sorts for ages now and getting nowhere. Can anyone point me in the right direction?
Thanks for any help.
Note: not really sure what's going on with the code; it doesn't appear to be pasting correctly.
Use below code, it can be a solution for you
public void JsonToArrayList(JSONArray myJsonArray) throws JSONException
{
ArrayList<Template> listItems = new ArrayList<Template>();
JSONObject jo = new JSONObject();
Template tem = new Template();
ListView lv = (ListView) findViewById(R.id.listView1);
String listItemString[] = new String[myJsonArray.length];
for(int i = 0; i<myJsonArray.length(); i++)
{
jo = myJsonArray.getJSONObject(i);
tem.username = jo.getString("username");
tem.email = jo.getString("user_email");
listItemString[i] = tem.username +" - " + tem.email; // u can change it according to ur need.
listItems.add(tem);
Log.e("Ninja Archives", tem.username);
}
// This is the array adapter, it takes the context of the activity as a first // parameter, the type of list view as a second parameter and your array as a third parameter
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, listItemString);
lv.setAdapter(arrayAdapter);
}
But better to write Custom adapter by extending BaseAdapter, and do listItem handling in getView method here is one simple tutorial
Take a class extending Base
private class CustomAdapter extends BaseAdapter
{
LayoutInflater inflater;
public CustomAdapter(Context context)
{
inflater = LayoutInflater.from(context);
}
public int getCount()
{
return listItems.size();
}
public Object getItem(int position)
{
return listItems.get(position);
}
public long getItemId(int position)
{
return position;
}
public View getView(final int position, View convertView,ViewGroup parent)
{
//if(convertView==null)
//convertView = inflater.inflate(R.layout.listlayout, parent, false);
Template data = (Template) getItem(position);
TextView v=new TextView(context);
v.setText(data.name);
return v;
}
}
and set adapter to your listview
lv.setAdapter(new CustomAdapter(this));
In this case you have to use a custom adapter (that extends from ArrayAdapter) and override the getView method to display in a custom layout the username and the email.

Categories

Resources