FaISalBLiNK
FaISalBLiNK

Reputation: 711

How to load more items in a ListView using AsyncTask or any other method

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

Answers (2)

D_Alpha
D_Alpha

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

Toukea Tatsi
Toukea Tatsi

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

Related Questions