如何使用 AsyncTask 或任何其他方法在 ListView 中加载更多项目 [英] How to load more items in a ListView using AsyncTask or any other method

查看:43
本文介绍了如何使用 AsyncTask 或任何其他方法在 ListView 中加载更多项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 android 开发很陌生,我知道这个问题可能是以前的答案,但我似乎找不到适合我的情况的答案.我正在创建一个 android 应用程序,它有一个 ListView 来显示项目列表.当用户到达 ListView 的页脚时,我需要显示更多项目(例如 10 个项目).我已经实现了 setOnScrollListener().我唯一需要您指导的问题是,当用户到达 ListView 底部时如何获得更多项目.我应该为它创建另一个 AsyncTask 吗?如果是,那么我该如何实现这一点...我目前正在展示 10 个项目,我正在使用 AsyncTask 通过 JSON 格式的 API 获取这些项目.下面是该 AsyncTask 的代码.

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 + "
");
                    }

                    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();
        }
    }

这是handleRecipeData()方法的代码:

private void handleRecipeData() {
        mProgressBar.setVisibility(View.INVISIBLE);
        if(mRecipeData == null){
            handleErrors();

        }else {
            try {
                getRecipeData();

            } catch (JSONException e) {
                Log.e(LOG_TAG,"Exception Caught: ",e);
            }
        }
    }

这是在 handleRecipeData() 方法中使用的 getRecipeData() 方法的代码:

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.

我还创建了一个自定义的 Adapter ExtendedSimpleAdapter.这是此适配器的代码.如果有人可能想查看它:

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;
    }

}

提前致谢

推荐答案

不要在每次调用数据时都会显示新数据时设置适配器.只需第一次设置,然后仅在收到来自 JSON 的新数据时通知适配器.

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();

更新--

1- 取一个布尔值来检查列表是否滚动 boolean iScrolling = false 并使其 trueonScroll 内()-

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
                }
            }
        });

现在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- 或者您可以借助另一个列表-获取另一个 List 并在其上添加数据并将此 List 添加到您的主 List 中,位于 getRecipeData()-

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;
        }
    }

更新-

更改您的 AsyncTask 参数-

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();
    }

希望它会有所帮助.

这篇关于如何使用 AsyncTask 或任何其他方法在 ListView 中加载更多项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆