I want to create Endless scroll view , list view data coming from server. i am created but when add new data then list view visible item started from start. And when add more than 70 rows then application crashed and error say array index out of bound.
I am new in android i am not able to use git hub library.
Please any one help me provide a simple example of endless list view or tutorial to use git hub library.
there my asyn class code
private class AlertSearchAsync extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
//pd.dismiss();
if(result.trim().contains("Result not found !"))
{
Toast.makeText(getApplicationContext(), result.trim(), Toast.LENGTH_LONG).show();
return;
}
else
{
mylist = new ArrayList<String>();
doc = XMLfunctions.XMLfromString(result);
// Toast.makeText(getApplicationContext(), ""+line, Toast.LENGTH_LONG).show();
NodeList nodes = doc.getElementsByTagName("JOB");
for (int i = 0; i < nodes.getLength(); i++) {
Element e = (Element) nodes.item(i);
pass_value.add(XMLfunctions.getValue(e, "id"));
if (!("null").equals(XMLfunctions.getValue(e, "location"))) {
mylist.add(XMLfunctions.getValue(e, "location"));
city_name.add(XMLfunctions.getValue(e, "location"));
} else {
mylist.add(" ");
}
if (!("null").equals(XMLfunctions.getValue(e, "title"))) {
mylist.add(XMLfunctions.getValue(e, "title"));
business_name.add(XMLfunctions.getValue(e, "title"));
} else {
mylist.add(" ");
}
if (!("null").equals(XMLfunctions.getValue(e, "state"))) {
mylist.add(XMLfunctions.getValue(e, "state"));
state_name.add(XMLfunctions.getValue(e, "state"));
} else {
mylist.add(" ");
}
if (!("null").equals(XMLfunctions.getValue(e, "company"))) {
mylist.add(XMLfunctions.getValue(e, "company"));
company_name.add(XMLfunctions.getValue(e, "company"));
} else {
mylist.add(" ");
}
if (!("null").equals(XMLfunctions.getValue(e, "url"))) {
mylist.add(XMLfunctions.getValue(e, "url"));
url_list.add(XMLfunctions.getValue(e, "url"));
} else {
mylist.add(" ");
}
if (!("null").equals(XMLfunctions.getValue(e, "description"))) {
mylist.add(XMLfunctions.getValue(e, "description"));
desc_list.add(XMLfunctions.getValue(e, "description"));
} else {
mylist.add(" ");
}
}
String[] company = new String[company_name.size()];
company = company_name.toArray(company);
String[] position = new String[business_name.size()];
position = business_name.toArray(position);
String[] state = new String[state_name.size()];
state = state_name.toArray(state);
String[] city = new String[city_name.size()];
city = city_name.toArray(city);
String[] url_str = new String[url_list.size()];
url_str = url_list.toArray(url_str);
String[] desc_str1 = new String[desc_list.size()];
desc_str1 = desc_list.toArray(desc_str1);
// datadap.setNotifyOnChange(false); // Prevents 'clear()' from clearing/resetting the listview
datadap.clear();
datadap= new Data(contect,company,position,city,state,pass_value,desc_str1);
// listView.setStackFromBottom(true);
// datadap.notifyDataSetChanged();
listView.setAdapter(datadap);
/* str_loc=str_locAlert;
str_desc=str_descAlert;
Toast.makeText(getApplicationContext(), "alert Class"+str_desc+str_loc, Toast.LENGTH_LONG).show();
Intent i= new Intent(Main_listview.this,Main_listview.class);
i.putExtra("line", result);
i.putExtra("limit", limit);
i.putExtra("Alert", true);
i.putExtra("str_Descrption",str_desc);
i.putExtra("str_location", str_loc);
startActivity(i); */
}
}
#Override
protected void onPreExecute()
{
//pd = ProgressDialog.show(Main_listview.this, "","Please wait...");
}
}
and i am load more data like this
listView.setOnScrollListener(new EndlessScrollListener() {
#Override
public void onLoadMore(int page, int totalItemsCount) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to your AdapterView
limit=limit+10;
// TODO Auto-generated method stub
AlertSearchAsync task1=new AlertSearchAsync();
String url="http://www.jobdiagnosis.com/fjobsrchservise.php?keyword="+
str_descAlert+
"&location="+str_locAlert+
"&start="+limit;
url=url.replace(" ", "%20");
//Toast.makeText(getApplicationContext(),"Limit"+limit, Toast.LENGTH_LONG).show();
task1.execute(url);
Log.d("URL ", url);
}
});
there my endlessscrollistner class
public abstract class EndlessScrollListener implements OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
// If there are no items in the list, assume that initial items are loading
if (!loading && (totalItemCount < previousTotalItemCount)) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading) {
if (totalItemCount > previousTotalItemCount) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
onLoadMore(currentPage + 1, totalItemCount);
loading = true;
}
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
I am relay sorry about my bad English
Please help me how we can create endless scroll list view
I think I might implement this the way that #commonsware does in this example: https://github.com/commonsguy/cwac-endless
Basically you create a ListView and attach an Adapter that automatically handles the endless scrolling and loading of Views.
See the class file here: https://github.com/commonsguy/cwac-endless/blob/master/src/com/commonsware/cwac/endless/EndlessAdapter.java
Related
I have a problem with the endless scroll. Every time it loads more data, it returns to the top view. What I want is the RecyclerView to stay in the last position when it loads new data.
I am trying to implement this code https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews-and-RecyclerView
here is the endless scroll code
public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener{
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 30;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
RecyclerView.LayoutManager mLayoutManager;
public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
}
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
}
else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScrolled(RecyclerView view, int dx, int dy) {
int lastVisibleItemPosition = 0;
int totalItemCount = mLayoutManager.getItemCount();
if (mLayoutManager instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
}
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
currentPage++;
onLoadMore(currentPage, totalItemCount, view);
loading = true;
}
}
// Call this method whenever performing new searches
public void resetState() {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
}
OnCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.booking_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.bookingRecyclerView);
linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setHasFixedSize(true);
scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
if(CurrentStatus.equals("notSearch")){
if (current < Integer.parseInt(TP)) {
current++;
loadMoreBookings(sort);
}
else if(current == Integer.parseInt(TP)){
Toast.makeText(getActivity(),"No More Data to Load", Toast.LENGTH_SHORT).show();
}
}else{
if (current < Integer.parseInt(TP)) {
current++;
searchMoreBookings(search, sort);
}
else if(current == Integer.parseInt(TP)){
Toast.makeText(getActivity(),"No More Data to Be Load", Toast.LENGTH_SHORT).show();
}
}
}
LoadMoreBookings
private void loadMoreBookings(final String sort){
CurrentStatus = "notSearch";
final ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Please Wait While Retrieving Data");
progressDialog.setCancelable(false);
progressDialog.show();
StringRequest requesting = new StringRequest(Request.Method.POST, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String JSONString) {
progressDialog.dismiss();
try{
JSONObject jsonTP = new JSONObject(JSONString);
JSONArray jsonArrayB = jsonTP.getJSONArray("Data");
for(int i = 0; i < jsonArrayB.length(); i++){
JSONObject o = jsonArrayB.getJSONObject(i);
Booking list = new Booking(
o.getString("bookID"),
o.getString("userEmail"),
o.getString("paymentMethod"),
o.getString("paymentStatus"),
o.getString("totalPrice"),
o.getString(String.valueOf("securityCode")),
o.getString(String.valueOf("travelDate")),
o.getString("paymentID"),
o.getString("userFN"),
o.getString("userLN"),
o.getString(String.valueOf("createdAt")),
o.getString("tTM"),
o.getString("messageToCustomer"),
o.getString("messageFromMerchant"),
o.getString("wCN"),
o.getString("wLocation"),
o.getString("wWebsite")
);
listBooking.add(list);
count++;
}
Toast.makeText(getActivity(), "Data : "+count, Toast.LENGTH_SHORT).show();
adapter = new BookingAdapter(listBooking,getActivity());
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
loadMoreBookings(sort);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(getActivity().getApplicationContext(), "Failed To Retrieve Data. Please Try Again.",Toast.LENGTH_LONG).show();
}
}
){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
String user = getActivity().getIntent().getStringExtra("username");
params.put("username", user);
params.put("currentpage", String.valueOf(current));
params.put("sorting", sort);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());
requestQueue.add(requesting);
}
set adapter in onCreateView()
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view = inflater.inflate(R.layout.booking_fragment, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.bookingRecyclerView);
linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new BookingAdapter(listBooking,getActivity());
recyclerView.setAdapter(adapter);
scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
if(CurrentStatus.equals("notSearch")){
if (current < Integer.parseInt(TP)) {
current++;
loadMoreBookings(sort);
}
else if(current == Integer.parseInt(TP)){
Toast.makeText(getActivity(),"No More Data to Load", Toast.LENGTH_SHORT).show();
}
}else{
if (current < Integer.parseInt(TP)) {
current++;
searchMoreBookings(search, sort);
}
else if(current == Integer.parseInt(TP)){
Toast.makeText(getActivity(),"No More Data to Be Load", Toast.LENGTH_SHORT).show();
}
}
}
don't set adapter every time just notify the adapter item inserted at position.
private void loadMoreBookings(final String sort){
CurrentStatus = "notSearch";
final ProgressDialog progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Please Wait While Retrieving Data");
progressDialog.setCancelable(false);
progressDialog.show();
StringRequest requesting = new StringRequest(Request.Method.POST, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String JSONString) {
progressDialog.dismiss();
try{
JSONObject jsonTP = new JSONObject(JSONString);
JSONArray jsonArrayB = jsonTP.getJSONArray("Data");
for(int i = 0; i < jsonArrayB.length(); i++){
JSONObject o = jsonArrayB.getJSONObject(i);
Booking list = new Booking(
o.getString("bookID"),
o.getString("userEmail"),
o.getString("paymentMethod"),
o.getString("paymentStatus"),
o.getString("totalPrice"),
o.getString(String.valueOf("securityCode")),
o.getString(String.valueOf("travelDate")),
o.getString("paymentID"),
o.getString("userFN"),
o.getString("userLN"),
o.getString(String.valueOf("createdAt")),
o.getString("tTM"),
o.getString("messageToCustomer"),
o.getString("messageFromMerchant"),
o.getString("wCN"),
o.getString("wLocation"),
o.getString("wWebsite")
);
listBooking.add(list);
adapter.notifyItemInserted(count);
count++;
}
Toast.makeText(getActivity(), "Data : "+count, Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
loadMoreBookings(sort);
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(getActivity().getApplicationContext(), "Failed To Retrieve Data. Please Try Again.",Toast.LENGTH_LONG).show();
}
}
){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
String user = getActivity().getIntent().getStringExtra("username");
params.put("username", user);
params.put("currentpage", String.valueOf(current));
params.put("sorting", sort);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());
requestQueue.add(requesting);
}
Following code is used for getting the new data from json on scroll of list view . But after getting the new json it does not add the new one from json instead it takes the same data that are in the first json .
Please Help me with this issue .
My Activity .
public class ProductView extends AppCompatActivity {
ListView list_product;
String json;
ProgressActivity loadingview;
int current_page = 1;
int totalPage = 1;
int Pagecount = 1;
Toolbar toolbar;
GetProductAdapter productAdapter;
List<BeanGetProducts> beanGetProductses = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_view);
toolbar = (Toolbar) findViewById(R.id.back_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ImageView img_home = (ImageView) findViewById(R.id.dr_image_home);
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ProductView.this, AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
list_product = (ListView) findViewById(R.id.list_products);
productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
list_product.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView absListView, int firstItem, int visibleItemCount, int totalItem) {
int total = firstItem + visibleItemCount;
if (Pagecount < totalPage) {
if (total == totalItem) {
Pagecount++;
new getProducts(Pagecount).execute();
productAdapter.notifyDataSetChanged();
list_product.setAdapter(productAdapter);
}
}
}
});
new getProducts(current_page).execute();
}
public class getProducts extends AsyncTask<Void, Void, String> {
int pageNo;
public getProducts(int pageNo) {
this.pageNo = pageNo;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
loadingview = new ProgressActivity(ProductView.this, "");
loadingview.setCancelable(false);
loadingview.show();
} catch (Exception e) {
}
}
#Override
protected String doInBackground(Void... voids) {
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("", String.valueOf(pageNo)));
json = new ServiceHandler().makeServiceCall(GlobalLinks.mainLink + GlobalLinks.productDetails, ServiceHandler.POST, pairs);
Log.e("Parameters", "" + pairs);
return json;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingview.dismiss();
System.out.println(s);
try {
if (!Internet.isConnectingToInternet(getApplicationContext())) {
Internet.noInternet(getApplicationContext());
} else {
if (s.equalsIgnoreCase(null) || s.equalsIgnoreCase("") || s.equalsIgnoreCase("null") || s.length() == 0) {
GlobalUse.nullJSON(getApplicationContext());
} else {
JSONObject mainObject = new JSONObject(s);
boolean status = mainObject.getBoolean("status");
String message = mainObject.getString("message");
totalPage = mainObject.getInt("total_page");
Log.e("total_page", "" + totalPage);
Toast.makeText(getApplicationContext(), "" + message, Toast.LENGTH_LONG).show();
if (status == true) {
JSONArray dataArray = mainObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object = dataArray.getJSONObject(i);
JSONObject getProductObject = object.getJSONObject("GetProduct");
BeanGetProducts getProducts = new BeanGetProducts();
getProducts.setProduct_id(getProductObject.getString("product_id"));
getProducts.setImage(getProductObject.getString("image"));
getProducts.setSku(getProductObject.getString("sku"));
getProducts.setQuantity(getProductObject.getString("quantity"));
getProducts.setPrice(getProductObject.getString("price"));
getProducts.setStock_status_id(getProductObject.getString("stock_status_id"));
JSONObject product_description = object.getJSONObject("Product_Description");
getProducts.setName(product_description.getString("name"));
getProducts.setDescription(product_description.getString("description"));
JSONObject SpecialPrice = object.getJSONObject("SpecialPrice");
getProducts.setSpecialPrice(SpecialPrice.getString("price"));
beanGetProductses.add(getProducts);
}
// productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
productAdapter.notifyDataSetChanged();
list_product.setAdapter(productAdapter);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}
Crate a new class named as EndlessScrollListener
import android.widget.AbsListView;
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum number of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it's still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn't currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
loading = onLoadMore(currentPage + 1, totalItemCount);
}
}
// Defines the process for actually loading more data based on page
// Returns true if more data is being loaded; returns false if there is no more data to load.
public abstract boolean onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
Then change your code as below.
The pagecount which you are passing in you asynctask is actually the size of a list. So you can update this variable this after laoding data from the network.
public class ProductView extends AppCompatActivity {
ListView list_product;
String json;
ProgressActivity loadingview;
int Pagecount = 0
Toolbar toolbar;
GetProductAdapter productAdapter;
List<BeanGetProducts> beanGetProductses = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_view);
toolbar = (Toolbar) findViewById(R.id.back_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ImageView img_home = (ImageView) findViewById(R.id.dr_image_home);
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ProductView.this, AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
list_product = (ListView) findViewById(R.id.list_products);
productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
// Load first time data and insert into list.
new getProducts(Pagecount).execute();
list_product.setOnScrollListener(new EndlessScrollListener() {
#Override
public boolean onLoadMore(int page, int totalItemsCount) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to your AdapterView
new getProducts(Pagecount).execute();
// or loadNextDataFromApi(totalItemsCount);
return true; // ONLY if more data is actually being loaded; false otherwise.
}
});
}
public class getProducts extends AsyncTask<Void, Void, String> {
int pageNo;
public getProducts(int pageNo) {
this.pageNo = pageNo;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
loadingv
iew = new ProgressActivity(ProductView.this, "");
loadingview.setCancelable(false);
loadingview.show();
} catch (Exception e) {
}
}
#Override
protected String doInBackground(Void... voids) {
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("", String.valueOf(pageNo)));
json = new ServiceHandler().makeServiceCall(GlobalLinks.mainLink + GlobalLinks.productDetails, ServiceHandler.POST, pairs);
Log.e("Parameters", "" + pairs);
return json;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingview.dismiss();
System.out.println(s);
try {
if (!Internet.isConnectingToInternet(getApplicationContext())) {
Internet.noInternet(getApplicationContext());
} else {
if (s.equalsIgnoreCase(null) || s.equalsIgnoreCase("") || s.equalsIgnoreCase("null") || s.length() == 0) {
GlobalUse.nullJSON(getApplicationContext());
} else {
JSONObject mainObject = new JSONObject(s);
boolean status = mainObject.getBoolean("status");
String message = mainObject.getString("message");
totalPage = mainObject.getInt("total_page");
Log.e("total_page", "" + totalPage);
Toast.makeText(getApplicationContext(), "" + message, Toast.LENGTH_LONG).show();
if (status == true) {
JSONArray dataArray = mainObject.getJSONArray("data");
// Update Pagecount here
Pagecount = Pagecount + dataArray.length();
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object = dataArray.getJSONObject(i);
JSONObject getProductObject = object.getJSONObject("GetProduct");
BeanGetProducts getProducts = new BeanGetProducts();
getProducts.setProduct_id(getProductObject.getString("product_id"));
getProducts.setImage(getProductObject.getString("image"));
getProducts.setSku(getProductObject.getString("sku"));
getProducts.setQuantity(getProductObject.getString("quantity"));
getProducts.setPrice(getProductObject.getString("price"));
getProducts.setStock_status_id(getProductObject.getString("stock_status_id"));
JSONObject product_description = object.getJSONObject("Product_Description");
getProducts.setName(product_description.getString("name"));
getProducts.setDescription(product_description.getString("description"));
JSONObject SpecialPrice = object.getJSONObject("SpecialPrice");
getProducts.setSpecialPrice(SpecialPrice.getString("price"));
beanGetProductses.add(getProducts);
productAdapter.notifyDataSetChanged();
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}
I have a fragment which contain listview that have some data from server and I am adding progressbar footer at bottom of listview when user scroll down listview a progress bar at bottom of listview is shown to user and send server request and add some more data in listview ,problem is that when scroll to end progressbar is also visible but sending server request back to back .How can I archeive this problem.
here is my code for listview scroll
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
Log.i("a", "scrolling stopped...");
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem + visibleItemCount == totalItemCount-1 && totalItemCount != 0) {
if (!isloading) {
// It is time to add new data. We call the listener
isloading = true;
if (NetworkUtil.isConnected(getActivity())) {
m_n_DefaultRecordCount = 5;// increment of record count by 5 on next load data
m_n_DeafalutLastCount = m_n_DeafalutLastCount + 5;// same here.....as above
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// convert int value to string
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// convert int value to string /////
loadmoreData();
} else {
Toast.makeText(getActivity(), "Please check internet connection !", Toast.LENGTH_LONG).show();
}
}
}
}
and here is my code for sending request when progressbar footer is shown to user in listview
public void loadmoreData() {
try {
String json;
// 3. build jsonObject
final JSONObject jsonObject = new JSONObject();// making object of Jsons.
jsonObject.put("agentCode", m_szMobileNumber);// put mobile number
jsonObject.put("pin", m_szEncryptedPassword);// put password
jsonObject.put("recordcount", sz_RecordCount);// put record count
jsonObject.put("lastcountvalue", sz_LastCount);// put last count
Log.d("CAppList:",sz_RecordCount);
Log.d("Capplist:",sz_LastCount);
// 4. convert JSONObject to JSON to String
json = jsonObject.toString();// convert Json object to string
System.out.println("Server Request:-" + json);
requestQueue = Volley.newRequestQueue(getActivity());
jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, CServerAPI.m_DealListingURL, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println("Response:-" + response);
try {
JSONArray posts = response.optJSONArray("dealList");// GETTING DEAL LIST
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.getJSONObject(i);// GETTING DEAL AT POSITION AT I
item = new CDealAppDatastorage();// object create of DealAppdatastorage
item.setM_szHeaderText(post.getString("dealname"));//getting deal name
item.setM_szsubHeaderText(post.getString("dealcode"));// getting deal code
item.setM_szDealValue(post.getString("dealvalue"));
if (!s_oDataset.contains(item)) {
s_oDataset.add(item);
}
}
isloading=false;
m_oAdapter.notifyDataSetChanged();
if (response.getString("resultdescription").equalsIgnoreCase("Connection Not Available")) {//server based conditions
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Connection Lost !", getActivity());
} else if (response.getString("resultdescription").equalsIgnoreCase("Deal List Not Found")) {// serevr based conditions .....
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "No more deals available", getActivity());
m_ListView.removeFooterView(mFooter);
requestQueue.cancelAll(TAG);
} else if (response.getString("resultdescription").equalsIgnoreCase("Technical Failure")) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Technical Failure", getActivity());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error:-" + error);
if (error instanceof TimeoutError) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Connection lost ! Please try again", getActivity());
} else if (error instanceof NetworkError) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "No internet connection", getActivity());
}
}
});
requestQueue.add(jsonObjectRequest);
} catch (JSONException e) {
e.printStackTrace();
}
}
All you need to do is maintain a flag for network request and one for noMoreDataLeft.
boolean noMoreDataLeft;
boolean requestGoingOn;
Everytime when you make a network call just change the value of requestGoingOn to true. And whene you come to know throught your api that there is no more data on server make the noMoreDataLeft true.
Now define two constants for show loading and data row -
private final static int TYPE_LOADING = 0;
private final static int TYPE_DATA = 1;
Now -
#Override
public int getItemCount() {
return data.size() + (requestGoingOn && !isNoMoreDataLeft ? 1 : 0);
}
It will add a more row when request is going on. Now you just need to check the current position if it is more than data.size then return type as loading.
#Override
public int getItemViewType(int position) {
return position >= data.size() ? TYPE_LOADING : TYPE_DATA;
}
That's it, now itemType will be available so you can decide which view you need to show. Hope it will help :)
I am trying to load data from api and trying to list only 10 item at a time and when i reach the bottom of list then i should load next 10 data on list and so on.
But when the data is loaded the list is scrolled back to the top, but i want that the focus of list should be remain unchanged just the next data should load.
here is the code :
lvCategory = (ListView) myFragmentView.findViewById(R.id.lvCategory);
lvCategory.setOnScrollListener(new AbsListView.OnScrollListener() {
private int currentVisibleItemCount;
private int currentScrollState;
private int currentFirstVisibleItem;
private int totalItem;
private LinearLayout lBelow;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.currentScrollState = scrollState;
this.isScrollCompleted();
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
this.currentFirstVisibleItem = firstVisibleItem;
this.currentVisibleItemCount = visibleItemCount;
this.totalItem = totalItemCount;
}
private void isScrollCompleted() {
if (totalItem - currentFirstVisibleItem == currentVisibleItemCount
&& this.currentScrollState == SCROLL_STATE_IDLE) {
/** To do code here*/
Toast.makeText(getContext(), "end of scroll", Toast.LENGTH_SHORT).show();
pageno++;
getListData(pageno);
Toast.makeText(getContext(), "set focus before", Toast.LENGTH_SHORT).show();
lvCategory.setSelection(5);
Toast.makeText(getContext(), "set focus after", Toast.LENGTH_SHORT).show();
lvCategory.smoothScrollToPosition(11);
}
}
});
getListData(pageno);
and here is the code of getlistData
private void getListData(int pageNo) {
//String url = "http://httpbin.org/get?site=code&network=tutsplus";
// String url = "http://52.27.73.255/api/index.php/product/category/get/1/10";
// Request a string response
//List<Category> categoryList;
String noOfEntry ="10";
if(pageNo==1){
categoryList = new ArrayList<>();
}
String url = "http://52.27.73.255/api/index.php/product/category/get/"+pageNo+"/"+noOfEntry;
JsonObjectRequest jsonRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// the response is already constructed as a JSONObject!
try {
// String def = response.getString("url");
//response = response.getJSONObject("args");
String code = response.getString("code");
if(code.equals("1")) {
jsonArray = response.getJSONArray("document");
StringBuffer finalBufferedData = new StringBuffer();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject finalObject = jsonArray.getJSONObject(i);
Category category = new Category();
category.setCategoryID(finalObject.getString("CategoryID"));
category.setCategoryCompanyID(finalObject.getString("CategoryCompanyID"));
category.setCategoryName(finalObject.getString("CategoryName"));
category.setCategoryLogo(finalObject.getString("CategoryLogo"));
category.setCategoryIsActive(finalObject.getString("CategoryIsActive"));
category.setCategoryDescription(finalObject.getString("CategoryDescription"));
categoryList.add(category);
/* String catId = finalObject.getString("CategoryID");
String catCompanyId = finalObject.getString("CategoryCompanyID");
String catName = finalObject.getString("CategoryName");
String catLogo = finalObject.getString("CategoryLogo");
String catIsActive =finalObject.getString("CategoryIsActive");
finalBufferedData.append("" + i + catId + "-" + catCompanyId + "-" + catName + "\n");
*/
}
Toast.makeText(getContext(), "setAdapter before", Toast.LENGTH_SHORT).show();
CateoryAdapter adapter = new CateoryAdapter(getActivity(), R.layout.custom_layout, categoryList);
Toast.makeText(getContext(), "setAdapter before", Toast.LENGTH_SHORT).show();
lvCategory.setAdapter(adapter);
Toast.makeText(getContext(), "after setAdapter", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getContext(), "staus code 0", Toast.LENGTH_SHORT).show();
}
//responsetextview.setText(finalBufferedData.toString());
// String site = response.getString("site"),
// network = response.getString("network");
//System.out.println("Site: " + site + "\nNetwork: " + network);
//Toast.makeText(getContext(), "getListData is executing", Toast.LENGTH_SHORT).show();
//responsetextview.setText(def);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
Volley.newRequestQueue(getContext()).add(jsonRequest);
}
what should i do so that the focus of the listview doesnot come back to the top of listview and it should remain where it was.
please help.
Because you create a new adapter and set it to the list.
Instead of:
CateoryAdapter adapter = new CateoryAdapter(getActivity(), R.layout.custom_layout, categoryList);
lvCategory.setAdapter(adapter);
Just add the new data to your adapter (the old one, don't create a new adapter), then call adapter.notifyDataSetChanged(); to refresh the ListView.
Here is my code displaying a list that is being parsed from an html file.
private class getItemDesc extends AsyncTask<Void, Void, Void> {
private ArrayList<String> descArray;
#Override
protected Void doInBackground(Void... arg0) {
try {
File file = new File(dir, getString(R.string.html_file));
descArray = new ArrayList<String>();
FileInputStream in = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(
in, "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
Document doc = Jsoup.parse(line);
Elements descs = doc.select("p");
for (Element desc : descs) {
descArray.add(desc.text());
}
}
in.close();
br.close();
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void v) {
MyAdapter mAdapter = new MyAdapter(getApplicationContext(),
R.layout.list_layout, descArray);
listView.setAdapter(mAdapter);
}
There is a lot of data coming from this (over 100 items in the array) and it's taking a while to load. I was wondering if there is a way to load 10 items at a time and use an OnScrollListener to continue loading the data from the file? Any suggestions will be appreciated.
Unfortunetly I haven't used that approach before but how about loading for instance 10 elements when list is scrolled to the very bottom . It can be done by simply reseting the adapter , yet there's a question of efficienty . But in my opinion 10 elements would do the thing.
lv = (ListView)findViewById(R.id.list_view);
adapter = new CustomAdaper(this ,/* List of elements*/);
lv.setAdapter(adapter);
lv.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
//Check if the last view is visible
if (++firstVisibleItem + visibleItemCount > totalItemCount) {
adapter = new CustomAdapter(getApplicationContext() , /*UpdateYourListData*/)
lv.setAdapter(adapter);
}
}
});
So basicly whenever ListView reach bottom you need to create new Adapter if with List of current + 10 elements.
I would use a Streaming Parser either from GSON or JacksonJSON.
Example from GSON docs:
JsonStreamParser parser = new JsonStreamParser(br); // br is your BufferedReader()
JsonElement element;
synchronized (parser) { // synchronize on an object shared by threads
if (parser.hasNext()) {
element = parser.next();
}
}
I would add extra to do call on listAdapter.notifyDataSetChanged() // ON MAIN THREAD whenever you hit 10. There's obviously other ways you can organize the code.
I have a full blown pagination example here.
There appear to be many ways to accomplish running background code when you reach the end of a listview, the following snippet is what I chose to implement:
lv.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
int threshold = 1;
int count = lv.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (lv.getLastVisiblePosition() >= count - threshold) {
items = (AddItems) new AddItems().execute(count);
}
}
}
});
As for the class AddItem, what I wanted required creating a custom array object, Gift()
public class Gift {
private String descs;
private String itemName;
private String price;
private String imageUrl;
public Gift() {
}
public Gift(String p, String i, String d, String u) {
this.descs = d;
this.itemName = i;
this.price = p;
this.imageUrl = u;
}
public String getDetails() {
return descs;
}
public void setDetails(String details) {
this.descs = details;
}
} // You get the idea
Then I would have to iterate through the file, adding desired strings to their respect ArrayList, and combine all three lists into an ArrayList<Gift> which is shown below.
private class AddItems extends AsyncTask<Integer, Void, ArrayList<Gift>> {
#Override
protected ArrayList<Gift> doInBackground(Integer... integer) {
try {
amountArray = new ArrayList<String>();
itemArray = new ArrayList<String>();
descArray = new ArrayList<String>();
imageUrls = new ArrayList<String>();
finalArray = new ArrayList<Gift>();
File file = new File(Ids.dir, getString(R.string.html_file));
FileInputStream in = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(
in, "UTF-8"));
String line;
int itemNumber = 0;
while ((line = br.readLine()) != null) {
Document doc = Jsoup.parse(line);
Elements titles = doc.select("h4[class=title]");
Elements amounts = doc.select("div[class=price]");
Elements descs = doc.select("p");
Elements urls = doc.select("img[class=gallery-image]");
for (Element price : amounts) {
itemNumber++;
amountArray.add(price.text());
}
for (Element title : titles) {
itemArray.add(title.text());
}
for (Element desc : descs) {
descArray.add(desc.text());
}
for (Element url : urls) {
imageUrls.add(url.attr("src"));
}
// totalShowing is a final integer with a value of 10
// which only iterates through 10 objects plus
// integer[0], which is the total number of items
// shown in the listview.
if (itemNumber == totalShowing + integer[0] + 1) {
break;
}
}
in.close();
br.close();
finalArray = new ArrayList<Gift>();
// Only add to finalArray the items after position integer[0]
// so we don't add items we've already added
for (int i = integer[0]; i < amountArray.size(); i++) {
finalArray.add(new Gift(amountArray.get(i), itemArray
.get(i), descArray.get(i), imageUrls.get(i)));
}
} catch (Exception e) {
e.printStackTrace();
}
return finalArray;
}
#Override
protected void onPostExecute(ArrayList<Gift> result) {
super.onPostExecute(result);
da.addItems(result);
}
}
After that, all I had to do was change my adapter to extend ArrayList<Gift> and add the following code:
public void addItems(ArrayList<Gift> newItems) {
if (null == newItems || newItems.size() <= 0) {
return;
}
if (null == finalArray) {
finalArray = new ArrayList<Gift>();
}
finalArray.addAll(newItems);
notifyDataSetChanged();
}