notifyDataSetChanged() doesn't refresh ListView - java

I have the following problem:
I am trying to load some data from firebase and after the data is loaded and stored in a HashMap I call the "updateAdapter" function (declared in the adapter below) and although the data has being changed the ListView doesn't refresh until some later random-(IMO) moment. I read couple of posts related to my problem and tried different solutions suggested there but they don't fix my problem. And by the way - Yes, I checked if the adapter loses the reference to the list and it doesn't.
My adapter looks like this:
public class NoteAdapterHashMap extends BaseAdapter{
private ArrayList mData = new ArrayList();
public NoteAdapterHashMap(Map<String, Note> map) {
mData.addAll(map.entrySet());
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Map.Entry<String, Note> getItem(int position) {
return (Map.Entry) mData.get(position);
}
#Override
public long getItemId(int position) {
// TODO implement logic with ID
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
if (convertView == null) {
result = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_note_listview, parent, false);
} else {
result = convertView;
}
Note note = getItem(position).getValue();
if(note!=null){
TextView title = (TextView) result.findViewById(R.id.list_note_title);
TextView date = (TextView) result.findViewById(R.id.list_note_date);
TextView content = (TextView) result.findViewById(R.id.list_note_content);
title.setText(note.getmTitle());
date.setText(note.getDateFormatted(parent.getContext()));
content.setText(note.getmContent());
if(note.getmContent().length()>50){
content.setText(note.getmContent().substring(0,50));
}
}
return result;
}
public void updateAdapter(HashMap<String,Note> map){
this.mData.clear();
this.mData.addAll(map.entrySet());
this.notifyDataSetChanged();
}
#Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
}
}
Thanks in advance !

Related

How do I replace a String[ ] with a ArrayList?

I'm trying to populate my gridview with images using picasso. I'm using jsoup to collect the image links and placing them into a ArrayList. I have something wrong with my ImageAdapter cause none of my images load when I start the app. My log shows the links being collected so that works. Any help will be appreciated. I'm posting the entire code for the Activity.
public class MainActivity extends Activity
{GridView grid;
String url="http://dstreet.site/";
String link,title,src;
ArrayList list= new ArrayList();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Scrapper();
grid = (GridView)findViewById(R.id.grid);
grid.setAdapter(new ImageAdapter(this, list));
}
public class ImageAdapter extends BaseAdapter {
ArrayList list;
private LayoutInflater inflater;
Context c;
int mCount;
ImageAdapter(Context context, ArrayList list) {
inflater = LayoutInflater.from(context);
c = context;
mCount = list.size();
this.list=list;
}
#Override
public int getCount() {
return mCount;
}
#Override
public Object getItem(int position) {
return true;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View
convertView, ViewGroup parent) {
final ViewHolder holder;
View view = convertView;
if (view == null) {
view = inflater.inflate(R.layout.img, parent,
false);
holder = new ViewHolder();
assert view != null;
holder.imageView = (ImageView)
view.findViewById(R.id.image);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
Picasso.get()
.load(list.get(position))
.placeholder(R.drawable.ic_launcher)
.error(R.drawable.ic_launcher)
.fit()
.into(holder.imageView, new Callback() {
#Override
public void onError(Exception p1)
{holder.imageView.setVisibility(View.INVISIBLE);
// TODO: Implement this method
}
#Override
public void onSuccess() {
holder.imageView.setVisibility(View.VISIBLE);
}
});
return view;
}
}
static class ViewHolder {
ImageView imageView;
}
public void Scrapper()
{
Content content= new Content();
content.execute();
}
public class Content extends
AsyncTask<Void,Void,Void>
{
#Override
protected Void doInBackground(Void[] p1)
{
// TODO: Implement this method
try
{
Document doc = Jsoup.connect(url).get();
// Identify Table Class "worldpopulation"
for (Element table :
doc.select("div[class=poster]")) {
Elements imgSrc =
table.select("img[src]");
// Get only src from img src
src = imgSrc.attr("src");
list.add(src);
}
Log.d("image links",list.toString());
}
catch (IOException e)
{e.printStackTrace();
}
return null;
}
}}
If you want to replace String[] with ArrayList then you need to use ArrayList.get(position) instead of IMAGE_URLS [position].
It looks like you're not iterating over the elements after you queried the table for images:
for (Element table : doc.select("div[class=poster]")) {
Elements imgSrc = table.select("img[src]");
src = imgSrc.attr("src");
list.add(src);
}
Something like this should do it:
doc.select("div[class=poster]") // get list of div
.stream() // for each div
.map(table -> table.select("img[src]")) // find all images
.flatmap(Elements::stream) // collapse images into 1 list
.map(imgSrc -> imgSrc.attr("src")) // for each image
.forEach(list::add); // add to Collection

How to pass data to getView method

I'm getting a variable data sent from activity to my adapter by using
sendData method, but every time when I try to access it in my getView method it resets to 0, please help. I've tried to debug code to check if the data from an activity is passing and it looks ok. I also created a getNumb method but still, the variable resets to 0. Here is my adapter code:
public class WorkoutListAdapterTwo extends BaseAdapter {
private int y;
public WorkoutListAdapterTwo() {
}
public int sendData(int x){
this.y = x;
return y;
}
public int getNumb(){
return this.y;
}
private static LayoutInflater mLayoutInflater = null;
public WorkoutListAdapterTwo(Activity ctx) {
this.mLayoutInflater = ctx.getLayoutInflater();
}
#Override
public int getCount() {
return WorkoutContentTwo.WORKOUTSTWO.size();
}
#Override
public Object getItem(int position) {
return WorkoutContentTwo.WORKOUTSTWO.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
int j = getNumb();
WorkoutTwo workout = (WorkoutTwo) getItem(j);
String [] arrOfStrings = workout.name.split(",");
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.adapter_workout_row, parent, false);
holder = new ViewHolder();
holder.id = (TextView) convertView.findViewById(R.id.workout_id);
holder.name = (TextView) convertView.findViewById(R.id.workout_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Set the content for the ListView row
//holder.id.setText(workout.id);
//holder.name.setText(arrOfStrings[i]);
holder.id.setText(Integer.toString(position+1));
holder.name.setText(workout.ArrList[position]);
// Set the color for the ListView row
holder.id.setBackgroundColor(workout.dark);
holder.name.setBackgroundColor(workout.light);
return convertView;
}
Here I'm adding the code where I'm calling my method:
public void onItemSelected(int position) {
// Start the detail activity for the selected workout ID.
Intent detailIntent = new Intent(this, WorkoutDetailActivityTwo.class);
detailIntent.putExtra(WorkoutDetailFragmentTwo.ARG_WORKOUT_POS, position);
WorkoutListAdapterTwo newAdd = new WorkoutListAdapterTwo();
newAdd.sendData(position);
newAdd.notifyDataSetChanged();
startActivity(detailIntent);
}
Are you notifying your adapter to update views after updating the value? If your sendData() is not called until after the adapter has done it's first draw, you will need to call notifyDataSetChanged() so that the adapter knows there are new values that should be used to update your views.
You have to make a interface or you can a use notifyDataSetChanged depends on the use if you are doing search operation then use the notifyDataSetChanged method but if you want to send some data then
Fragment or activity
public class ExampleFragment extends Fragment implements MyAdapter.SuccessResponse{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.my_layout, container, false);
MyAdapter myAdapter = new MyAdapter(getActivity(), 0);
myAdapter.successResponse = this;
return contentView;
}
#Override
public void onSuccess() {
}
}
The adapter code
class MyAdapter extends ArrayAdapter{
SuccessResponse successResponse;
public MyAdapter(Context context, int resource) {
super(context, resource);
}
public interface SuccessResponse{
void onSuccess();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//ur views
linearLayout.setOnClickListener(new View.OnClickListener{
#Override
public void onClick (View view){
if(successResponse!=null)
successResponse.onSuccess();
}
})
}
}
You can use any type of adapter i am use arrayadaper here.

Android Icon/Image setting pattern for multiple choices

What pattern do I have to use, if I have ListView in which ImageView and like 500 different icons that could be set on that ImageView. Should I just write If/Switch statement, or there is another way/pattern to do it?. Thanks in advance!
Let me assume that you know what icon(I mean the name of icon) to be loaded into the imageView and those icons are available in your drawable resource folder. In this case
#Override
public void onBindViewHolder(final RecyclerAdapter.ViewHolder holder, int position) {
DataItem dataItem = dataList.get(holder.getAdapterPosistion());
try {
int resID = activityContext.getResources().getIdentifier(dataItem.getIconName() , "drawable"/**resource folder name*/, activityContext.getPackageName());
holder.imageView.setBackgroundResource(resID);
} catch (Exception e) {
throw new RuntimeException("Error getting Resource ID.", e)
}
}
Where are these icons that you want to set? you are getting them from server or they are stored locally in your application file? or they are from user phone gallery?
Here is the code you want for your adapter:
public class MyAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private ArrayList<String> mIconNames;
public MyAdapter(Context context) {
mContext = context;
mIconNames = getIconNames();
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return mIconNames.size();
}
#Override
public Object getItem(int position) {
return mIconNames.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get view for row item
View rowView = mInflater.inflate(R.layout.your_layout, parent, false);
ImageView thumbnailImageView =
(ImageView) rowView.findViewById(R.id.your_image_view_id);
Picasso.with(mContext).load(mIconNames.get(position)).placeholder(R.mipmap.ic_launcher).into(thumbnailImageView);
return rowView;
}
//this method builds your icon names
private ArrayList<String> getIconNames() {
ArrayList<String> iconNames = new ArrayList<>();
int numberOfIcons = 99;
String iconBaseName = "icon";
for (int i = 1; i < numberOfIcons; i++) {
iconNames.add(iconBaseName + i);
}
return iconNames;
}
}

Android - Custom ListView Viewholder

I am trying to display detailed Product information in an custom Listview with two TextViews per row for the key/value pair. The data is displayed correct. I also colored every second line different.
And there is my Problem. If I scroll up and down the different colored rows change their color and remain in this state. The data is not affected from this problem. Just the backroundcolor of the TextViews. I use the ViewHolder Pattern but this did not change anything. I added the code of the adapter. I think thats enough. Have you any idea?
Screenshot of the problem:
Code:
public class ProductDetailAdapter extends BaseAdapter {
private LinkedHashMap<String,String> list;
private Context context;
public ProductDetailAdapter(Context c, LinkedHashMap<String,String> list){
super();
this.context = c;
this.list=list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ProductDetailAdapter.ViewHolder viewHolder;
if(convertView == null){
convertView=inflater.inflate(R.layout.product_detail_data_row,null);
viewHolder = new ViewHolder();
viewHolder.textViewKey = (TextView) convertView.findViewById(R.id.productDataKey);
viewHolder.textViewValue = (TextView) convertView.findViewById(R.id.productDataValue);
convertView.setTag(viewHolder);
}else {
viewHolder = (ProductDetailAdapter.ViewHolder) convertView.getTag();
}
viewHolder.textViewKey.setText((String)list.keySet().toArray()[position]);
viewHolder.textViewValue.setText(list.get(list.keySet().toArray()[position]));
if(position % 2 == 0){
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
}
return convertView;
}
private static class ViewHolder {
public TextView textViewKey;
public TextView textViewValue;
public ViewHolder(){};
}
}
That happens because the rows are being recycled. It's a common problem.
You can solve it by doing:
if(position % 2 == 0){
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite2));
} else {
viewHolder.textViewKey.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite1)); //Or the color that you want for odd rows
viewHolder.textViewValue.setBackgroundColor(context.getResources().getColor(R.color.colorParkerWhite1)); //Or the color that you want for odd rows
}
Try this:
super( c, 0, list );
instead of this:
super();
Once you pass the data source to the adapter you no longer need :
getCount
getItem
getItemId
please refer this link and link2 and link3 these will work for you

Converting Map to Linkedlist hashmap adapter

I have a LinkedList HashMap List<HashMap<String, String>>that I have created, I'm trying to send it to a custom adapter that I found but it is for a Map. What the best way to convert it to accept LinkedList Hashmap?
public class CustomListOutageAdapter extends BaseAdapter {
private final ArrayList mData;
public CustomListOutageAdapter( List<HashMap<String, String>> map) {
mData = new ArrayList();
mData.add(map);
}
#Override
public int getCount() {
return mData.size();
}
#Override
public HashMap.Entry<String, String> getItem(int position) {
return (HashMap.Entry) mData.get(position);
}
#Override
public long getItemId(int position) {
// TODO implement you own logic with ID
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
if (convertView == null) {
result = LayoutInflater.from(parent.getContext()).inflate(R.layout.mylistoutagedetails, parent, false);
} else {
result = convertView;
}
HashMap.Entry<String, String> item = getItem(position);
// TODO replace findViewById by ViewHolder
((TextView) result.findViewById(R.id.name)).setText(item.getKey());
((TextView) result.findViewById(R.id.item)).setText(item.getValue());
return result;
}
}

Categories

Resources