I've a listview which shows values from web service. Its fine when it loads the listview. But when I click on any item to open a new fragment (which shows details of the item) and get back to the same listview, its items doubles everytime. For example, if I have (in original) 5 items in total. Then when I get back from the fragment, the total count will be 10, then 15 and so on. It means the app is adding all items again and again. I searched for the solution and did what were the general solution like adapter.notifyDataSetChanged() but its still gets duplicated. If anyone can show me the problem, I would be grateful.
public class CustomListAdapter extends ArrayAdapter<Model> {
private Context mContext;
int resource;
private ArrayList<Model> mListData = new ArrayList<Model>();
public CustomListAdapter(Context mContext, int resource, ArrayList<Model> mListData) {
super(mContext, resource, mListData);
this.resource = resource;
this.mContext = mContext;
this.mListData = mListData;
}
public void setListData(ArrayList<Model> mListData) {
this.mListData = mListData;
notifyDataSetChanged();
}
#Override
public int getCount() {
return super.getCount();
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
final ViewHolder holder;
if (v == null) {
holder = new ViewHolder();
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
v = inflater.inflate(resource, parent, false);
holder.custname = (TextView) v.findViewById(R.id.cust_name);
holder.date = (TextView) v.findViewById(R.id.date);
holder.staffname = (TextView) v.findViewById(R.id.staff_name);
holder.time = (TextView) v.findViewById(R.id.time);
holder.service = (TextView) v.findViewById(R.id.service);
holder.refid = (TextView) v.findViewById(R.id.refid);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
final Model item = mListData.get(position);
holder.custname.setText(item.getCustname());
holder.date.setText(item.getDate());
holder.staffname.setText(item.getStaffname());
holder.time.setText(item.getTime());
holder.service.setText(item.getService());
holder.refid.setText(item.getRefid());
return v;
}
class ViewHolder {
TextView custname, date, staffname, time, service, refid;
}
}
public class ListFrag extends Fragment{
private SwipeMenuListView listView;
private CustomListAdapter adapter;
private CShowProgress cShowProgress;
private SQLiteHandler db;
private String uid, bookingId;
private ArrayList<Model> arrayList = new ArrayList<>();
private static final String BOOKED_LIST = "http://192.168.220.13/android/showbookinglist";
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.listfrag, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
listView = (SwipeMenuListView)view.findViewById(R.id.list);
db = new SQLiteHandler(getActivity());
cShowProgress = CShowProgress.getInstance();
fetchDetails();
adapter = new CustomListAdapter(getActivity(), R.layout.listitem, arrayList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String a = arrayList.get(i).getCustname();
String b = arrayList.get(i).getStaffname();
String c = arrayList.get(i).getService();
String d = arrayList.get(i).getDate();
String e = arrayList.get(i).getTime();
String f = arrayList.get(i).getRefid();
String g = arrayList.get(i).getEmail();
String h = arrayList.get(i).getServprice();
String j = arrayList.get(i).getSpeclprice();
String k = arrayList.get(i).getStatus();
db.addDetails(a, b, c, d, e, f, g, h, j, k);
DetailsView details = new DetailsView();
((Bookings)getActivity()).replaceFragment(details);
}
});
}
private void fetchDetails() {
cShowProgress.showProgress(getActivity());
StringRequest stringRequest = new StringRequest(Request.Method.POST, BOOKED_LIST,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
cShowProgress.hideProgress();
try {
JSONArray jsonArray = new JSONArray(response);
for(int i=0; i<jsonArray.length(); i++){
JSONObject obj = jsonArray.getJSONObject(i);
Model model = new Model();
model.setCustname(obj.getString("customername"));
model.setDate(obj.getString("staffdate"));
model.setStaffname(obj.getString("staffname")+"(Staff)");
model.setTime(obj.getString("stafftime"));
model.setService(obj.getString("servicename"));
model.setRefid(obj.getString("booking_referenceid"));
model.setEmail(obj.getString("customeremail"));
model.setServprice(obj.getString("serviceprice"));
model.setSpeclprice(obj.getString("specialprice"));
model.setStatus(obj.getString("status"));
model.setBookid(obj.getString("bookingid"));
arrayList.add(model);
}
adapter.notifyDataSetChanged();
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "VolleyError" + error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("spaid", "145");
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(stringRequest);
}
}
try to change it as.. B'coz you are adding the elements in previously created list.. So you have to clear it.
private void fetchDetails() {
if(arrayList!=null )arrayList.clear(); // this line
cShowProgress.showProgress(getActivity());
The thing is that when you get back to the fragment it is recreated and onViewCreated is called again. From there you call again fetchDetails() and then your are adding the whole List for a second time to the adapter. So you can clear the list before fetchDetails() or just if you have to fetch them again.
change your try - catch block of onResponse method by below.
try {
JSONArray jsonArray = new JSONArray(response);
arrayList = new ArrayList<>();
for(int i=0; i<jsonArray.length(); i++)
{
JSONObject obj = jsonArray.getJSONObject(i);
Model model = new Model();
model.setCustname(obj.getString("customername"));
model.setDate(obj.getString("staffdate"));
model.setStaffname(obj.getString("staffname")+"(Staff)");
model.setTime(obj.getString("stafftime"));
model.setService(obj.getString("servicename"));
model.setRefid(obj.getString("booking_referenceid"));
model.setEmail(obj.getString("customeremail"));
model.setServprice(obj.getString("serviceprice"));
model.setSpeclprice(obj.getString("specialprice"));
model.setStatus(obj.getString("status"));
model.setBookid(obj.getString("bookingid"));
arrayList.add(model);
}
adapter.notifyDataSetChanged();
This is happening because you are not clearing the arrayList. Due to this every time that you construct the array and the adapter, you are adding the elements into an array that already has elements.
That why you have 5, then 10, then 15 and so on..
Clear the array before adding new elements
arrayList.clear();
Or program another strategy like:
Not populate the array every time you return to the fragment.
Check if he element existe before add it into the array.
Related
I get data in JSON from API, and there are id and url. Now, i need to create a button "Add to favorites" for each image that i display. When i try to set adapter.setListener(this);, i get an error, because i can't use string format.
How can i resolve this problem? I spend 5 hours on this, and can't resolve it :(
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listItem);
favorites = findViewById(R.id.buttonFav);
catDetailsArrayList = new ArrayList<>();
myAdapter = new MyAdapter(MainActivity.this ,catDetailsArrayList);
searchbtn = findViewById(R.id.buttonSearch);
searchbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
catDetailsArrayList.clear();
myAdapter.notifyDataSetChanged();
displayCats();
}
});
});
}
private void displayCats() {
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try{
JSONArray jsonArray = new JSONArray(response);
for(int i=0; i<jsonArray.length(); i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
String jsonCatUrl2 = jsonObject1.getString("url");
String jsonCatId2 = jsonObject1.getString("id");
CatDetails catDetails = new CatDetails();
catDetails.setUrl(jsonCatUrl2);
catDetails.setId(jsonCatId2);
catDetailsArrayList.add(catDetails);
}
listView.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
} catch(JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),error.getMessage(),Toast.LENGTH_LONG).show();
}
});
requestQueue.add(stringRequest);
}
MyAdapter:
public class MyAdapter extends BaseAdapter {
public Activity activity;
public ArrayList<CatDetails> catDetailsArrayList;
public LayoutInflater inflater;
Button btn;
TextView idnr;
public MyAdapter(Activity activity, ArrayList<CatDetails> catDetailsArrayList) {
this.activity = activity;
this.catDetailsArrayList = catDetailsArrayList;
}
#Override
public Object getItem(int position) {
return catDetailsArrayList.get(position);
}
#Override
public long getItemId(int position) {
return (long)position;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (inflater == null) {
inflater = this.activity.getLayoutInflater();
}
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
}
ImageView imageView = convertView.findViewById(R.id.ImageView);
final CatDetails catDetails = this.catDetailsArrayList.get(position);
Picasso.get().load(catDetails.getUrl()).into(imageView);
idnr =convertView.findViewById(R.id.textView);
btn = convertView.findViewById(R.id.buttonFav);
final String id = catDetails.getId();
idnr.setText(catDetails.getId());
return convertView;
}
#Override
public int getCount() {
return this.catDetailsArrayList.size();
}
I display the id that i receive from server for each item, it's ok, but i don't know how to set the button "add to favorites" to works fine. It must receive item id (that i received from server) as a param, but id is in string format.
final String id = catDetails.getId();
change it to
final String id = Integer.toString(catDetails.getId());
I want to get 2 api url from json to bind them into one listview in android. One api read data detail and another read image so both of them into the same listview to show detail information.
Here is my first api to get text detail
public class NationalNewsFragment extends Fragment
{
SwipeRefreshLayout swipeRefreshLayout;
private ProgressDialog progressDialog;
ListView listView;
ImageView frontbanner;
//NEWS API
RequestQueue queue;
ArrayList<HashMap<String, String>> dataList = new ArrayList<HashMap<String,
String>>();
static final String KEY_TITLE = "Title";
static final String KEY_INFO1 = "info1";
static final String KEY_C_DATE = "C_date";
static final String KEY_News_ID = "News_ID";
static final String KEY_C_BY = "C_by";
static final String KEY_C_VIEWS = "C_views";
//FrontBanner API
RequestQueue requestQueue;
static final String FRONT_BANNER = "Adv";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_national_news, container,
false);
listView = (ListView)view.findViewById(R.id.list_source);
swipeRefreshLayout =
(SwipeRefreshLayout)view.findViewById(R.id.refresh_layout);
//NEWS API
queue = Volley.newRequestQueue(getContext());
requestQueue = Volley.newRequestQueue(getContext());
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage("Loading...");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
String url = "my api url here";
JsonArrayRequest jsonArrayRequest = new
JsonArrayRequest(Request.Method.GET, url, null,
new Response.Listener<JSONArray>()
{
#Override
public void onResponse(JSONArray response)
{
for (int i = 0; i < response.length(); i++)
{
try
{
JSONObject news = response.getJSONObject(i);
HashMap<String, String> map = new
HashMap<String, String>();
map.put(KEY_TITLE,
news.optString(KEY_TITLE).toString());
map.put(KEY_INFO1,
news.optString(KEY_INFO1).toString());
map.put(KEY_C_DATE,
news.optString(KEY_C_DATE).toString());
map.put(KEY_News_ID,
news.optString(KEY_News_ID).toString());
map.put(KEY_C_BY,
news.optString(KEY_C_BY).toString());
map.put(KEY_C_VIEWS,
news.optString(KEY_C_VIEWS).toString());
//System.out.println(news.optString(KEY_TITLE).toString());
dataList.add(map);
ListNewsAdapter adapter = new
ListNewsAdapter(getActivity(), dataList);
listView.setAdapter(adapter);
} catch (JSONException e)
{
e.printStackTrace();
}
}
progressDialog.cancel();
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
error.printStackTrace();
}
});
queue.add(jsonArrayRequest);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent i = new Intent(getActivity(),
FreshNewsDetailActivity.class);
i.putExtra("News_ID", dataList.get(position).get(KEY_News_ID));
startActivity(i);
//Toast.makeText(MainActivity.this,
dataList.get(position).get(KEY_News_ID), Toast.LENGTH_SHORT).show();
}
});
//Refresh layout
swipeRefreshLayout.setOnRefreshListener(new
SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
swipeRefreshLayout.setRefreshing(false);
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage("Loading...");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
String url = "my api url here";
JsonArrayRequest jsonArrayRequest = new
JsonArrayRequest(Request.Method.GET, url, null,
new Response.Listener<JSONArray>()
{
#Override
public void onResponse(JSONArray response)
{
for (int i = 0; i < response.length(); i++)
{
try
{
JSONObject news =
response.getJSONObject(i);
HashMap<String, String> map = new
HashMap<String, String>();
map.put(KEY_TITLE,
news.optString(KEY_TITLE).toString());
map.put(KEY_INFO1,
news.optString(KEY_INFO1).toString());
map.put(KEY_C_DATE,
news.optString(KEY_C_DATE).toString());
map.put(KEY_News_ID,
news.optString(KEY_News_ID).toString());
//System.out.println(news.optString(KEY_TITLE).toString());
dataList.add(map);
ListNewsAdapter adapter = new
ListNewsAdapter(getActivity(), dataList);
listView.setAdapter(adapter);
} catch (JSONException e)
{
e.printStackTrace();
}
}
progressDialog.cancel();
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
error.printStackTrace();
}
});
queue.add(jsonArrayRequest);
listView.setOnItemClickListener(new
AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent i = new Intent(getActivity(),
FreshNewsDetailActivity.class);
i.putExtra("News_ID",
dataList.get(position).get(KEY_News_ID));
startActivity(i);
//Toast.makeText(MainActivity.this,
dataList.get(position).get(KEY_News_ID), Toast.LENGTH_SHORT).show();
}
});
}
});
return view;
}
}
Here is my dataAdapter code. Should I use one adapter? If so how to combine two datasource into the same dataAdapter. Or should I should use 2 dataAdapter and how to bind two dataAdapter into the same ListView in Android ?
class ListNewsAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
public ListNewsAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ListNewsViewHolder holder = null;
if (convertView == null)
{
holder = new ListNewsViewHolder();
convertView =
LayoutInflater.from(activity).inflate(R.layout.source_layout, parent,
false);
holder.title = (TextView) convertView.findViewById(R.id.title);
holder.c_by = (TextView) convertView.findViewById(R.id.c_by);
holder.c_views = (TextView) convertView.findViewById(R.id.c_views);
holder.c_date = (TextView) convertView.findViewById(R.id.c_date);
convertView.setTag(holder);
}
else
{
holder = (ListNewsViewHolder) convertView.getTag();
}
holder.title.setId(position);
holder.c_by.setId(position);
holder.c_views.setId(position);
holder.c_date.setId(position);
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
try
{
holder.c_by.setText("ដោយ
"+song.get(NationalNewsFragment.KEY_C_BY));
holder.c_views.setText("/
"+song.get(NationalNewsFragment.KEY_C_VIEWS)+" views");
String sourceString = "<p align=\\\"justify\\\"><b><font
color=#000000>" + song.get(NationalNewsFragment.KEY_TITLE) + "</font></b> "
+ song.get(NationalNewsFragment.KEY_INFO1)+"</p>";
holder.title.setText(Html.fromHtml(sourceString));
holder.c_date.setText("ថ្ងៃទី ៖
"+song.get(NationalNewsFragment.KEY_C_DATE));
}
catch(Exception e) {}
return convertView;
}
}
class ListNewsViewHolder
{
TextView title, info1, c_date, c_by, c_views;
}
Should use one adapter. With complex data source (ex: need to fetch from multiple APIs) you should do some research about Reactive Programming. If apply Reactive Java + Android, you can do it by a few lines of code.
From the files, u have shared I got to know that you are using ClassCallApi to fetch both APIs. If so,
Create a new model class
public class CombinedApi {
private ArrayList<HashMap<String, String>> dataListOne;
private ArrayList<HashMap<String, String>> dataListTwo;
public ArrayList<HashMap<String, String>> getDataListOne() {
return dataListOne;
}
public void setDataListOne(ArrayList<HashMap<String, String>> dataListOne) {
this.dataListOne = dataListOne;
}
public ArrayList<HashMap<String, String>> getDataListTwo() {
return dataListTwo;
}
public void setDataListTwo(ArrayList<HashMap<String, String>> dataListTwo) {
this.dataListTwo = dataListTwo;
}
}
Make some changes to your ClassCallApi
ArrayList<CombinedApi> dataList = new ArrayList();
ArrayList<HashMap<String, String>> dataListOne = new ArrayList<HashMap<String, String>>();
ArrayList<HashMap<String, String>> dataListTwo = new ArrayList<HashMap<String, String>>();
Once you complete the FIRST API CALL save data to dataListOne and once after you completed SECOND API CALL succesfully add that data to dataListTwo
dataListOne.add(map); //Data from api call one
dataListTwo.add(map); //Data from api call two
Please do use your logic to feed the above arrays.
Once u have both data. Create a simple function inside ClassCallApi to feed adapter
private void feedAdapter() {
for (int i = 0; i < dataListOne.size(); i++) {
CombinedApi mCombinedApi = new CombinedApi();
mCombinedApi.setDataListOne(dataListOne.get(i));
mCombinedApi.setDataListTwo(dataListTwo.get(i)); //Here i am assuming that both ArrayList have same size
dataList.add(mCombinedApi);
}
ListNewsAdapter adapter = new ListNewsAdapter(getActivity(), dataList);
listView.setAdapter(adapter);
}
A small change in Adapter as well.
private ArrayList<CombinedApi> data;
public ListNewsAdapter(Activity a, ArrayList<CombinedApi> d) {
activity = a;
data=d;
}
All set :)
To get song
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
instead use
song = data.get(position).getDataListOne();
or
song = data.get(position).getDataListTwo();
My listview is showing the last item twice.
I want to show the members from database with volley and MySQL, sending request from android to API which is programmed in PHP and the API returns
JSON data.
Here is my code:
String email, member_id, member_type;
ListView community_member_list;
Context context = this;
MemberAdapter memberAdapter;
List<Model> modelList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_community);
SharedPreferences SP = getSharedPreferences("MemberSession", MODE_PRIVATE);
Boolean member_logged_in = SP.getBoolean("member_logged_in", false);
email = SP.getString("email", null);
member_id = SP.getString("member_id", null);
member_type = SP.getString("member_type", null);
if (!member_logged_in)
{
Intent intent = new Intent(this, Login.class);
startActivity(intent);
finish();
}else{
community_member_list = (ListView) findViewById(R.id.community_members_list);
memberAdapter = new MemberAdapter(getApplicationContext(), R.layout.community_list_item, modelList);
community_member_list.setAdapter(memberAdapter);
get_community_members();
}
}
public void get_community_members()
{
StringRequest stringRequest = new StringRequest(Request.Method.POST, new Login().site_url+"community",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("members");
Model model = null;
for(int i=0; i<jsonArray.length(); i++) {
JSONObject finalObject = jsonArray.getJSONObject(i);
model = new Model();
model.setMember_id(finalObject.getInt("physician_id"));
model.setProfile_photo(finalObject.getString("profile_photo"));
model.setFirst_name(finalObject.getString("first_name"));
model.setLast_name(finalObject.getString("last_name"));
model.setDesignation(finalObject.getString("designation"));
model.setOrganization(finalObject.getString("organization"));
modelList.add(model);
}
memberAdapter.add(model);
memberAdapter.setNotifyOnChange(true);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "Error "+error, Toast.LENGTH_SHORT).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("member_id", member_id);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private class MemberAdapter extends ArrayAdapter {
private List<Model> memberList;
private int resource;
private LayoutInflater inflater;
MemberAdapter(Context context, int resource, List<Model> objects) {
super(context, resource, objects);
memberList = objects;
this.resource = resource;
inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
if(convertView == null)
{
convertView = inflater.inflate(resource, null);
}
final ImageView imageView;
TextView textView, textView2;
imageView = (ImageView)convertView.findViewById(R.id.imageView);
textView = (TextView)convertView.findViewById(R.id.textView);
textView2 = (TextView) convertView.findViewById(R.id.textView2);
com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage("http://www.plexusd.com/uploads/specialist/" + memberList.get(position).getProfile_photo(), imageView, new ImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
imageView.setImageResource(R.mipmap.avatar);
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
imageView.setImageResource(R.mipmap.avatar);
}
});
textView.setText("Dr. "+memberList.get(position).getFirst_name()+" "+memberList.get(position).getLast_name());
textView2.setText(""+memberList.get(position).getDesignation()+",\n"+memberList.get(position).getOrganization());
return convertView;
}
}
Here is the picture of list from mobile.
Remove memberAdapter.add(model); inside onResponse after for loop. model object holds the last object and you are adding that in adapter again so last object showing 2 times.
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray jsonArray = jsonObject.getJSONArray("members");
Model model = null;
for(int i=0; i<jsonArray.length(); i++) {
JSONObject finalObject = jsonArray.getJSONObject(i);
model = new Model();
model.setMember_id(finalObject.getInt("physician_id"));
model.setProfile_photo(finalObject.getString("profile_photo"));
model.setFirst_name(finalObject.getString("first_name"));
model.setLast_name(finalObject.getString("last_name"));
model.setDesignation(finalObject.getString("designation"));
model.setOrganization(finalObject.getString("organization"));
modelList.add(model);
}
memberAdapter.add(model); // remove this.
memberAdapter.setNotifyOnChange(true);
} catch (JSONException e) {
e.printStackTrace();
}
you added model twice , one of it in the loop ,not of it after the loop
So I made an sliding tabs app that loads json into a listview. My question is how would I implement something that would only load 5 listview items in the beginning and would load another 5 when you scroll down? (Instead of loading all of the listview items in the beginning)
I have search the web and I can't really understand how to do this. Any suggestions or ideas will be appreciated.
This is some of my code. These classes is where I think the code would go: I used SlidingTabLayout & strip from the android developer site.
CustomListAdapter code:
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Tanga> tangasItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Tanga> movieItems) {
this.activity = activity;
this.tangasItems = movieItems;
}
#Override
public int getCount() {
return tangasItems.size();
}
#Override
public Object getItem(int location) {
return tangasItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row, null);
TextView name = (TextView) convertView.findViewById(R.id.name);
// getting movie data for the row
Tanga m = tangasItems.get(position);
// title
name.setText(m.getName());
return convertView;
}
}
Fragment:
public class Tab1 extends Fragment {
private static final String url = "website.json";
private List<Tanga> tangaList = new ArrayList<Tanga>();
private ListView listView;
private CustomListAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void onActivityCreated (Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
listView = (ListView) getView().findViewById(R.id.list);
adapter = new CustomListAdapter(getActivity(), tangaList);
listView.setAdapter(adapter);
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Tanga movie = new Tanga();
//name
String name = obj.getString("name");
movie.setName(name);
// adding movie to movies array
tangaList.add(movie);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Error: ");
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(movieReq);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tabs, container, false);
return v;
}
}
Tanga Code: (model)
public class Tanga {
private String name;
public Tanga() {
}
public Tanga(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
There are multiple ways you could handle this, the simplest way would be to create another ArrayList of type Tanga, let's suppose it's name is tangaList2. What you have to do is in your for loop write this code.
public void onResponse(JSONArray response) {
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Tanga movie = new Tanga();
//name
String name = obj.getString("name");
movie.setName(name);
// adding movie to movies array
if(i < 5) {
tangaList.add(movie);
}
else {
tangaList2.add(movie);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
Now after this you should also implement the onScrollListener in your Fragment:
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if ((++firstVisibleItem) + visibleItemCount > totalItemCount) {
for(int i = 0; i < 5 && tangaList2.size() > 0; i++){
tangaList.add(tangaList2.get(0));
tangaList2.remove(0);
}
}
}
});
I've got a ListView with a 'show next results' button. The list is filled by a custom adapter extending BaseAdapter. Using it as shown below, only the new results are shown.
How can I append the new results to the list?
ListView listView = (ListView)findViewById(android.R.id.list);
// Show next results button
View footerView = ((LayoutInflater)ItemList.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_listview, null, false);
listView.addFooterView(footerView);
footerView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = getIntent();
i.putExtra("firstIndex", mFirstIndex + NRES_PER_PAGE);
i.putExtra("itemCount", NRES_PER_PAGE);
startActivity(i);
}
});
mItems = json.getJSONArray("data");
setListAdapter(new ItemAdapter(ItemList.this, mType, mItems));
FIX
ListActivity
public class ItemList extends MenuListActivity{
ItemAdapter mItemAdapter;
Integer mFirstIndex = 0;
JSONArray mItems = new JSONArray();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.item_list);
// Set data adapter
mItemAdapter = new ItemAdapter(ItemList.this, mType, mItems);
ListView listView = (ListView)findViewById(android.R.id.list);
View footerView = ((LayoutInflater)ItemList.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_listview, null, false);
listView.addFooterView(footerView);
footerView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = MyProgressDialog.show(ItemList.this, null, null);
mFirstIndex = mFirstIndex + ITEM_COUNT;
new GetItemInfoList().execute();
}
});
setListAdapter(mItemAdapter);
new GetItemInfoList().execute();
}
private class GetItemInfoList extends AsyncTask<Void, Void, JSONObject> {
protected JSONObject doInBackground(Void... params) {
// Set POST data to send to web service
List<NameValuePair> postData = new ArrayList<NameValuePair>(2);
postData.add(new BasicNameValuePair("firstindex", Integer.toString(mFirstIndex)));
postData.add(new BasicNameValuePair("itemscount", Integer.toString(ITEM_COUNT)));
JSONObject json = RestJsonClient.getJSONObject(URL_ITEMINFOLIST, postData);
return json;
}
protected void onPostExecute(JSONObject json) {
try {
// Get data from json object and set to list adapter
JSONArray jsonArray = json.getJSONArray("data");
for(int i=0; i<jsonArray.length(); i++)
mItems.put(jsonArray.get(i));
mItemAdapter.notifyDataSetChanged();
ListView listView = (ListView)findViewById(android.R.id.list);
View footerView = ((LayoutInflater)ItemList.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_listview, null, false);
listView.addFooterView(footerView);
footerView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = MyProgressDialog.show(ItemList.this, null, null);
mFirstIndex = mFirstIndex + ITEM_COUNT;
new GetItemInfoList().execute();
}
});
} catch (JSONException e) {
}
}
}
}
Adapter
public class ItemAdapter extends BaseAdapter {
private Context mContext;
private LayoutInflater mInflater;
private JSONArray mItems;
private ImageLoader mImageLoader;
private int mCategory;
public ItemAdapter(Context context, int category, JSONArray items) {
mContext = context;
mInflater = LayoutInflater.from(context);
mItems = items;
mCategory = category;
this.mImageLoader = new ImageLoader(context, true);
}
public int getCount() {
return mItems.length();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_row, null);
holder = new ViewHolder();
holder.listitem_pic = (ImageView) convertView.findViewById(R.id.listitem_pic);
holder.listitem_desc = (TextView) convertView.findViewById(R.id.listitem_desc);
holder.listitem_title = (TextView) convertView.findViewById(R.id.listitem_title);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
try {
JSONObject item = mItems.getJSONObject(position);
String listitem_pic = item.getString("picture");
holder.listitem_pic.setTag(listitem_pic);
mImageLoader.DisplayImage(listitem_pic, (Activity)mContext, holder.listitem_pic);
holder.listitem_title.setText(item.getString("title"));
holder.listitem_desc.setText(item.getString("desc"));
}
catch (JSONException e) {
}
return convertView;
}
static class ViewHolder {
TextView listitem_title;
ImageView listitem_pic;
TextView listitem_desc;
}
}
It depends on your implementation of ItemAdapter, I'd recommend holding a reference to ItemAdapter, then updating the data set behind it and then calling notifyDataSetChanged() on it. something like:
ItemAdapter ia = new ItemAdapter(ItemList.this, mType, mItems);
setListAdapter(ia);
footerView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mItems.append(newItems);
ia.notifyDataSetChanged();
}
});
It is tricky without knowing what data you are using or whether you have the entire data set available at the start.