Reputation: 711
I am very new to android development and I know that this question might be answer before but I can't seem to find a suitable answer for my situation. I am creating an android app which have a ListView
to show list of items. I need to show more items (like 10 more items) when the user reaches the footer of the ListView
. I have implemented the setOnScrollListener()
. My only issue and for which I need your guidance is that how can I get more items when the user reaches the bottom of the ListView
. Should I create another AsyncTask
for it? If yes then how can I ahieve this ... I am currently showing 10 items and I am getting those items through an API in JSON
format using an AsyncTask
. Below is the code for that AsyncTask
.
public class GetRecipeData extends AsyncTask<Object, Void, JSONObject> {
public final int NUMBER_OF_POSTS = 10;
int responseCode = -1;
JSONObject recipeJsonResponse = null;
@Override
protected JSONObject doInBackground(Object... params) {
try {
URL blogFeedUrl = new URL("http://www.bestfoodrecipesever.com/api/get_category_posts/?slug="+RECIPE_CAT+"&count="+NUMBER_OF_POSTS);
HttpURLConnection connection = (HttpURLConnection) blogFeedUrl.openConnection();
connection.setRequestMethod("GET");
connection.connect();
responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK){
InputStream inputStream = connection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
String recipeDataJsonStr = buffer.toString();
recipeJsonResponse = new JSONObject(recipeDataJsonStr);
}else {
Log.i(LOG_TAG, "Unsuccessful HTTP Response Code: " + responseCode);
}
}
catch (MalformedURLException e){
Log.e(LOG_TAG,"Exception Caught: ",e);
}
catch (IOException e) {
Log.e(LOG_TAG, "IO Exception Caught: ",e);
}
catch (Exception e) {
Log.e(LOG_TAG,"Exception Caught: ",e);
}
return recipeJsonResponse;
}
@Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
mRecipeData = result;
handleRecipeData();
}
}
Here is the code for the handleRecipeData()
Method:
private void handleRecipeData() {
mProgressBar.setVisibility(View.INVISIBLE);
if(mRecipeData == null){
handleErrors();
}else {
try {
getRecipeData();
} catch (JSONException e) {
Log.e(LOG_TAG,"Exception Caught: ",e);
}
}
}
And Here is the code for the getRecipeData()
Method which is being used within the handleRecipeData()
Method:
private void getRecipeData() throws JSONException {
JSONArray jsonPosts = mRecipeData.getJSONArray("posts");
mRecipePostData = new ArrayList<>();
for (int i = 0; i < jsonPosts.length(); i++){
JSONObject post = jsonPosts.getJSONObject(i);
String title = post.getString(KEY_TITLE);
title = Html.fromHtml(title).toString();
String author = post.getJSONObject(KEY_AUTHOR).getString("name");
author = Html.fromHtml(author).toString();
String imgUrl = post.getJSONObject(KEY_IMG_URL).getJSONObject("full").getString("url");
String recipeContent = post.getString(KEY_CONTENT);
recipeContent = Html.fromHtml(recipeContent).toString();
String recipeUrl = post.getString(KEY_RECIPE_URL);
HashMap<String, String> singleRecipePost = new HashMap<>();
singleRecipePost.put(KEY_TITLE, title);
singleRecipePost.put(KEY_AUTHOR, author);
singleRecipePost.put(KEY_IMG_URL, imgUrl);
singleRecipePost.put(KEY_CONTENT, recipeContent);
singleRecipePost.put(KEY_RECIPE_URL, recipeUrl);
mRecipePostData.add(singleRecipePost);
}
String[] keys = {KEY_TITLE};
int[] ids = {R.id.list_recipe_title};
mRecipeAdapter = new ExtendedSimpleAdapter(getContext(), mRecipePostData, R.layout.itemlistrow, keys, ids);
listView.setAdapter(mRecipeAdapter);
mRecipeAdapter.notifyDataSetChanged();
}
I am really stuck with this issue ... Can somebody help me out with this ... I would be greatful to you.
I also created a custom Adapter ExtendedSimpleAdapter. Here is the code for this Adapter. In case someone might want to review it:
public class ExtendedSimpleAdapter extends SimpleAdapter {
Context context2;
public ExtendedSimpleAdapter(Context context, List<? extends Map<String, String>> data, int resource, String[] from, int[] to){
super(context, data, resource, from, to);
context2=context;
}
public View getView(int position, View convertView, ViewGroup parent){
// here you let SimpleAdapter built the view normally.
View v = super.getView(position, convertView, parent);
// Then we get reference for Picasso
//TextView recipeTitle = (TextView) v.getTag();
ImageView recipeThumb = (ImageView) v.getTag();
if(recipeThumb == null){
//recipeTitle = (TextView) v.findViewById(R.id.list_recipe_title);
recipeThumb = (ImageView) v.findViewById(R.id.list_recipe_thumb);
//v.setTag(recipeTitle);
v.setTag(recipeThumb); // <<< THIS LINE !!!!
}
// get the url from the data you passed to the `Map`
String TAG_IMAGE = "thumbnail_images";
String url = ((Map<String,String>) getItem(position)).get(TAG_IMAGE);
// do Picasso
// maybe you could do that by using many ways to start
Picasso.with(context2).load(url).resize(300, 200).centerCrop().into(recipeThumb);
// return the view
return v;
}
}
Thanks in advance
Upvotes: 0
Views: 1158
Reputation: 4069
Do not set adapter every time it will show you new data all the time when you will call for data. Just set it first time then only notify the adapter when you received new data from JSON.
Or you can use another List to store new data and add this list to your main List -
yourMainList.addAll(anotherList);
adapter.notifyDataSetChanged();
UPDATES--
1- Take a boolean value to check list is scrolling or not boolean iScrolling = false and make it true inside onScroll()-
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 && totalItemCount!=0) {
isScrolling = true;
mFooter.setVisibility(View.VISIBLE);
/*GetRecipeData getRecipeData = new GetRecipeData();
getRecipeData.execute();*/
GetRecipeData getRecipeData = new GetRecipeData();
getRecipeData.execute(yourCounts); // update
}
}
});
Now some changes inside getRecipeData()-
private void getRecipeData() throws JSONException {
JSONArray jsonPosts = mRecipeData.getJSONArray("posts");
mRecipePostData = new ArrayList<>();
for (int i = 0; i < jsonPosts.length(); i++){
JSONObject post = jsonPosts.getJSONObject(i);
String title = post.getString(KEY_TITLE);
title = Html.fromHtml(title).toString();
String author = post.getJSONObject(KEY_AUTHOR).getString("name");
author = Html.fromHtml(author).toString();
String imgUrl = post.getJSONObject(KEY_IMG_URL).getJSONObject("full").getString("url");
String recipeContent = post.getString(KEY_CONTENT);
recipeContent = Html.fromHtml(recipeContent).toString();
String recipeUrl = post.getString(KEY_RECIPE_URL);
HashMap<String, String> singleRecipePost = new HashMap<>();
singleRecipePost.put(KEY_TITLE, title);
singleRecipePost.put(KEY_AUTHOR, author);
singleRecipePost.put(KEY_IMG_URL, imgUrl);
singleRecipePost.put(KEY_CONTENT, recipeContent);
singleRecipePost.put(KEY_RECIPE_URL, recipeUrl);
mRecipePostData.add(singleRecipePost);
}
String[] keys = {KEY_TITLE};
int[] ids = {R.id.list_recipe_title};
if (!isScrolling){
mRecipeAdapter = new ExtendedSimpleAdapter(getContext(), mRecipePostData, R.layout.itemlistrow, keys, ids);
listView.setAdapter(mRecipeAdapter);
mRecipeAdapter.notifyDataSetChanged();
}else{
mRecipeAdapter.notifyDataSetChanged();
isScrolling = false;
}
}
2- Or you can do it with the help of another List- Take another List and add data on it and add this List to your main List, inside getRecipeData()-
private void getRecipeData() throws JSONException {
JSONArray jsonPosts = mRecipeData.getJSONArray("posts");
if (!isScrolling) {
mRecipePostData = new ArrayList<>();
}else{
yourSecondList = new ArrayList<>();
}
for (int i = 0; i < jsonPosts.length(); i++){
JSONObject post = jsonPosts.getJSONObject(i);
String title = post.getString(KEY_TITLE);
title = Html.fromHtml(title).toString();
String author = post.getJSONObject(KEY_AUTHOR).getString("name");
author = Html.fromHtml(author).toString();
String imgUrl = post.getJSONObject(KEY_IMG_URL).getJSONObject("full").getString("url");
String recipeContent = post.getString(KEY_CONTENT);
recipeContent = Html.fromHtml(recipeContent).toString();
String recipeUrl = post.getString(KEY_RECIPE_URL);
HashMap<String, String> singleRecipePost = new HashMap<>();
singleRecipePost.put(KEY_TITLE, title);
singleRecipePost.put(KEY_AUTHOR, author);
singleRecipePost.put(KEY_IMG_URL, imgUrl);
singleRecipePost.put(KEY_CONTENT, recipeContent);
singleRecipePost.put(KEY_RECIPE_URL, recipeUrl);
if (!isScrolling) {
mRecipePostData.add(singleRecipePost);
}else{
yourSecondList.add(singleRecipePost);
}
}
String[] keys = {KEY_TITLE};
int[] ids = {R.id.list_recipe_title};
if (!isScrolling){
mRecipeAdapter = new ExtendedSimpleAdapter(getContext(), mRecipePostData, R.layout.itemlistrow, keys, ids);
listView.setAdapter(mRecipeAdapter);
mRecipeAdapter.notifyDataSetChanged();
}else{
mRecipePostData.addAll(yourSecondList);
mRecipeAdapter.notifyDataSetChanged();
isScrolling = false;
}
}
UPDATES-
Change your AsyncTask params-
public class GetRecipeData extends AsyncTask<String, Void, JSONObject> {
// your code..
@Override
protected JSONObject doInBackground(String... params) {
try {
URL blogFeedUrl = new URL("http://www.bestfoodrecipesever.com/api/get_category_posts/?slug=" + RECIPE_CAT + "&count=" + params[0]);
// your code...
}
}
}
And also make some change here-
if(isNetworkAvailable()) {
mProgressBar.setVisibility(View.VISIBLE);
GetRecipeData getRecipeData = new GetRecipeData();
getRecipeData.execute(yourCount);
} else {
Toast.makeText(getContext(),getString(R.string.no_network), Toast.LENGTH_LONG).show();
}
Hope it will help.
Upvotes: 1
Reputation: 199
try like this:
//used for populate the listView
private void populateListView(HashMap<String, String> datas){
if(mRecipeAdapter ==null){
String[] keys = {KEY_TITLE};
int[] ids = {R.id.list_recipe_title};
mRecipeAdapter = new ExtendedSimpleAdapter(getContext(), datas, R.layout.itemlistrow, keys, ids);
listView.setAdapter(mRecipeAdapter);
}else
{
mRecipeAdapter.notifyDataSetChanged();
}
}
//create ListView Data::: i have removed your five last line, and repleced them by return mRecipePostData
private ArrayList<HashMap<String,String>> getRecipeData() throws JSONException {
JSONArray jsonPosts = mRecipeData.getJSONArray("posts");
mRecipePostData = new ArrayList<HashMap<String,String>>();
for (int i = 0; i < jsonPosts.length(); i++){
JSONObject post = jsonPosts.getJSONObject(i);
String title = post.getString(KEY_TITLE);
title = Html.fromHtml(title).toString();
String author = post.getJSONObject(KEY_AUTHOR).getString("name");
author = Html.fromHtml(author).toString();
String imgUrl = post.getJSONObject(KEY_IMG_URL).getJSONObject("full").getString("url");
String recipeContent = post.getString(KEY_CONTENT);
recipeContent = Html.fromHtml(recipeContent).toString();
String recipeUrl = post.getString(KEY_RECIPE_URL);
HashMap<String, String> singleRecipePost = new HashMap<>();
singleRecipePost.put(KEY_TITLE, title);
singleRecipePost.put(KEY_AUTHOR, author);
singleRecipePost.put(KEY_IMG_URL, imgUrl);
singleRecipePost.put(KEY_CONTENT, recipeContent);
singleRecipePost.put(KEY_RECIPE_URL, recipeUrl);
mRecipePostData.add(singleRecipePost);
}
return mRecipePostData;
}
//after getData, i am populating ListView
private void handleRecipeData() {
mProgressBar.setVisibility(View.INVISIBLE);
if(mRecipeData == null){
handleErrors();
}else {
try {
HashMap<String, String> datas=getRecipeData();
populateListView(datas);
} catch (JSONException e) {
Log.e(LOG_TAG,"Exception Caught: ",e);
}
}
}
Upvotes: 0