在Android上的RecyclerView中加载更多数据时显示错误

时间:2016-04-27 11:05:01

标签: android json

我想开发一个网站的Android应用程序。我从json阅读网站帖子并在每10个帖子中显示它在RecyclerView中,当用户在RecyclerView上滚动显示更多10个帖子并结束时!在这个项目中我使用okHTTP v3,Glide和RecyclerView!
Json链接: JSON LINK
我可以加载前10个帖子,但是当在RecyclerView上滚动并显示其他10个帖子时,请告诉我这个错误:

04-27 15:34:33.599 3249-3249/com.tellfa.colony E/AndroidRuntime: FATAL EXCEPTION: main
                                                                 Process: com.tellfa.colony, PID: 3249
                                                                 java.lang.IndexOutOfBoundsException: Invalid index 11, size is 0
                                                                     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
                                                                     at java.util.ArrayList.get(ArrayList.java:308)
                                                                     at com.tellfa.colony.Activities.Main_page$1$1.run(Main_page.java:95)
                                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:135)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:5349)
                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                     at java.lang.reflect.Method.invoke(Method.java:372)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)

主要活动代码:

public class Main_page extends AppCompatActivity {

    private static final long RIPPLE_DURATION = 250;
    private Toolbar toolbar;
    private RelativeLayout root;
    private ImageView menu_image;
    private RecyclerView main_recyclerView;
    private MainAdapter2 mAdaper;
    private List<MainDataModel> dataModels = new ArrayList<MainDataModel>();
    private List<MainDataModel> dataModelsArray;
    private Context context;
    protected Handler handler;
    private RelativeLayout loadLayout;
    private LinearLayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_page);
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
        handler = new Handler();
        context = getApplicationContext();
        loadLayout = (RelativeLayout) findViewById(R.id.main_empty_layout);
        toolbar = (Toolbar) findViewById(R.id.main_toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            getSupportActionBar().setTitle(null);
        }
        LoadData();
        mLayoutManager = new LinearLayoutManager(this);
        // Menu
        root = (RelativeLayout) findViewById(R.id.main_root);
        View guillotineMenu = LayoutInflater.from(this).inflate(R.layout.menu_layout, null);
        root.addView(guillotineMenu);
        menu_image = (ImageView) toolbar.findViewById(R.id.toolbar_logo);
        new GuillotineAnimation.GuillotineBuilder(guillotineMenu, guillotineMenu.findViewById(R.id.menu_layout_image), menu_image)
                .setStartDelay(RIPPLE_DURATION)
                .setActionBarViewForAnimation(toolbar)
                .setClosedOnStart(true)
                .build();
        // RecyclerView and setData
        main_recyclerView = (RecyclerView) findViewById(R.id.main_recycler);
        main_recyclerView.setHasFixedSize(true);
        main_recyclerView.setLayoutManager(mLayoutManager);

        mAdaper = new MainAdapter2(this, main_recyclerView, dataModels);
        main_recyclerView.setAdapter(mAdaper);

        mAdaper.setOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                dataModels.add(null);
                mAdaper.notifyItemInserted(dataModels.size() - 1);
                dataModelsArray = new ArrayList<MainDataModel>();

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        dataModels.remove(dataModels.size() - 1);
                        mAdaper.notifyItemRemoved(dataModels.size());

                        int start = dataModels.size();
                        int end = start + 10;

                        for (int i = start + 1; i <= end; i++) {
                            dataModels.add(new MainDataModel(dataModelsArray.get(i).getId(),
                                    dataModelsArray.get(i).getTitle(),
                                    dataModelsArray.get(i).getContent(),
                                    dataModelsArray.get(i).getThumbnail()));
                            mAdaper.notifyItemInserted(dataModels.size());
                        }
                        mAdaper.setLoaded();

                    }
                }, 1000);
            }
        });
    }

    @Subscribe
    public void onEvent(List<MainDataModel> mainInfoModels) {
        mAdaper.add(mainInfoModels);

        if (dataModels.isEmpty()) {
            main_recyclerView.setVisibility(View.GONE);
            loadLayout.setVisibility(View.VISIBLE);

        } else {
            main_recyclerView.setVisibility(View.VISIBLE);
            loadLayout.setVisibility(View.GONE);
        }
    }

    private void LoadData() {
        MainDataInfo dataInfo = new MainDataInfo();
        // here getMainDataInfo() should return the server response
        dataInfo.getMainDataInfo(this);
    }
}

AsyncTask代码:

public class MainDataInfo {
    private Context mContext;
    private String ServerAddress = ServerIP.getIP();

    public void getMainDataInfo(Context context) {
        mContext = context;
        new getInfo().execute(ServerAddress + "page=1");
    }

    private class getInfo extends AsyncTask<String, Void, String> {
        EventBus bus = EventBus.getDefault();
        private String ou_response;
        private List<MainDataModel> infoModels;

        @Override
        protected void onPreExecute() {
            CustomProcessDialog.createAndShow(mContext);
            infoModels = new ArrayList<>();
        }

        @Override
        protected String doInBackground(String... params) {
            OkHttpClient client = new OkHttpClient();

            Request request = new Request.Builder()
                    .url(ServerAddress + "page=1")
                    .cacheControl(CacheControl.FORCE_NETWORK)
                    .build();

            Response response;
            try {
                response = client.newCall(request).execute();
                ou_response = response.body().string();
                response.body().close();
                if (ou_response != null) {
                    try {
                        JSONObject postObj = new JSONObject(ou_response);
                        JSONArray postsArray = postObj.optJSONArray("posts");
                        infoModels = new ArrayList<>();

                        for (int i = 0; i <= infoModels.size(); i++) {
                            JSONObject postObject = (JSONObject) postsArray.get(i);
                            JSONObject images=postObject.optJSONObject("thumbnail_images");
                            JSONObject imagesPair=images.optJSONObject("medium");

                            int id = postObject.getInt("id");
                            String title = postObject.getString("title");
                            String content = postObject.getString("content");
                            String thumbnail = imagesPair.getString("url");
                            Log.d("Data", "Post id: " + id);
                            Log.d("Data", "Post title: " + title);
                            Log.d("Data", "Post title: " + thumbnail);

                            //Use the title and id as per your requirement
                            infoModels.add(new MainDataModel(id, title, content, thumbnail));
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return ou_response;
        }

        @Override
        protected void onPostExecute(String result) {
            CustomProcessDialog.dissmis();
            if (result != null) {
                bus.post(infoModels);
            }
        }
    }
}

用于加载更多数据我使用接口类:OnLoadMoreListener

注意:请不要给我负面的积分,帮助我,我真的需要你的帮助!谢谢所有&lt; 3我该如何解决?

2 个答案:

答案 0 :(得分:0)

更改此代码

mAdaper.setOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                dataModels.add(null);
                mAdaper.notifyItemInserted(dataModels.size() - 1);
                dataModelsArray = new ArrayList<MainDataModel>();

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        dataModels.remove(dataModels.size() - 1);
                        mAdaper.notifyItemRemoved(dataModels.size());

                        int start = dataModels.size();
                        int end = start + 10;

                        for (int i = start + 1; i <= end; i++) {
                            dataModels.add(new MainDataModel(dataModelsArray.get(i).getId(),
                                    dataModelsArray.get(i).getTitle(),
                                    dataModelsArray.get(i).getContent(),
                                    dataModelsArray.get(i).getThumbnail()));
                            mAdaper.notifyItemInserted(dataModels.size());
                        }
                        mAdaper.setLoaded();

                    }
                }, 1000);
            }
        });

  mAdaper.setOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                dataModels.add(null);
                mAdaper.notifyItemInserted(dataModels.size() - 1);
              LoadData(pageNumber);
            }
        });

并更改此方法:

@Subscribe
    public void onEvent(List<MainDataModel> mainInfoModels) {
        mAdaper.add(mainInfoModels);

        if (dataModels.isEmpty()) {
            main_recyclerView.setVisibility(View.GONE);
            loadLayout.setVisibility(View.VISIBLE);

        } else {
            main_recyclerView.setVisibility(View.VISIBLE);
            loadLayout.setVisibility(View.GONE);
        }
    }

于: int pageNumber = 1;          @订阅             public void onEvent(List mainInfoModels){

    if(dataModels.size()>0){
            dataModels.remove(dataModels.size() - 1);
            mAdaper.notifyItemRemoved(dataModels.size());
            mAdaper.setLoaded();
            }

mAdaper.add(mainInfoModels);
        mAdapter.notifyDataSetChanged();
pageNumber++;

        if (dataModels.isEmpty()) {
            main_recyclerView.setVisibility(View.GONE);
            loadLayout.setVisibility(View.VISIBLE);

        } else {
            main_recyclerView.setVisibility(View.VISIBLE);
            loadLayout.setVisibility(View.GONE);
        }
    }

这只是我理解的概述:你没有对dataModelsArray做任何事情。 看看这个希望这有帮助。因为你没有提供所有代码

编辑: 对于你的第二个答案,你说10个帖子被重复显示,因为你没有传递页码:

更改此方法:

 public void getMainDataInfo(Context context) {
        mContext = context;
        new getInfo().execute(ServerAddress + "page=1");
    }

为:

 public void getMainDataInfo(Context context, int pageNumber) {
        mContext = context;
        new getInfo().execute(ServerAddress + "page="+pageNumber);
    }

将此方法更改为:

private void LoadData() {
        MainDataInfo dataInfo = new MainDataInfo();
        // here getMainDataInfo() should return the server response
        dataInfo.getMainDataInfo(this);
    }

 private void LoadData(int pageNumber) {
        MainDataInfo dataInfo = new MainDataInfo();
        // here getMainDataInfo() should return the server response
        dataInfo.getMainDataInfo(this, pageNumber);
    }
  

将LoadData()更改为LoadData(pageNumber)

在您的活动类中创建一个整数,在获得响应时递增它,并将递增的pageNumber传递给此方法。

谢谢希望它解决你的问题。接受它作为答案,因为其他人可以得到想法。

答案 1 :(得分:0)

尝试此代码:

并删除Don不使用您的MainDataInfo类。我已经在Main_Page.java中实现了它。

你的Main_Page.java:

  public class Main_page extends AppCompatActivity  {

private static final long RIPPLE_DURATION = 250;
private Toolbar toolbar;
private RelativeLayout root;
private ImageView menu_image;
private RecyclerView main_recyclerView;
private MainAdapter2 mAdaper;
private List<MainDataModel> dataModels = new ArrayList<MainDataModel>();
protected Handler handler;
private RelativeLayout loadLayout;
private LinearLayoutManager mLayoutManager;
private int pageCount = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_page);
    handler = new Handler();
    loadLayout = (RelativeLayout) findViewById(R.id.main_empty_layout);
    toolbar = (Toolbar) findViewById(R.id.main_toolbar);
    if (toolbar != null) {
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle(null);
    }
    LoadData(pageCount);
    mLayoutManager = new LinearLayoutManager(Main_page.this);
    // Menu
    root = (RelativeLayout) findViewById(R.id.main_root);
    View guillotineMenu = LayoutInflater.from(Main_page.this).inflate(R.layout.menu_layout, null);
    root.addView(guillotineMenu);
    menu_image = (ImageView) toolbar.findViewById(R.id.toolbar_logo);
    new GuillotineAnimation.GuillotineBuilder(guillotineMenu, guillotineMenu.findViewById(R.id.menu_layout_image), menu_image)
            .setStartDelay(RIPPLE_DURATION)
            .setActionBarViewForAnimation(toolbar)
            .setClosedOnStart(true)
            .build();
    // RecyclerView and setData
    main_recyclerView = (RecyclerView) findViewById(R.id.main_recycler);
    main_recyclerView.setHasFixedSize(true);
    main_recyclerView.setLayoutManager(mLayoutManager);


    mAdaper.setOnLoadMoreListener(new OnLoadMoreListener() {
        @Override
        public void onLoadMore() {
            dataModels.add(null);
            mAdaper.notifyItemInserted(dataModels.size() - 1);

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    dataModels.remove(dataModels.size() - 1);
                    mAdaper.notifyItemRemoved(dataModels.size());

                    LoadData(++pageCount);
                }
            }, 1000);
        }
    });
}
  /*
@Subscribe
public void onEvent(List<MainDataModel> mainInfoModels) {
    mAdaper.add(mainInfoModels);

    if (dataModels.isEmpty()) {
        main_recyclerView.setVisibility(View.GONE);
        loadLayout.setVisibility(View.VISIBLE);

    } else {
        main_recyclerView.setVisibility(View.VISIBLE);
        loadLayout.setVisibility(View.GONE);
    }
}*/

private void LoadData(int pageNumber) {
    new APIInfoAsyncTask().execute(ServerAddress + "page=" + pageNumber);
}


private class APIInfoAsyncTask extends AsyncTask<String, Void, List<MainDataModel>> {
    private String ou_response;



    @Override
    protected void onPreExecute() {
        CustomProcessDialog.createAndShow(Main_page.this);
    }

    @Override
    protected List<MainDataModel> doInBackground(String... params) {
        OkHttpClient client = new OkHttpClient();

        List<MainDataModel> responseData = new ArrayList<>();

        Request request = new Request.Builder()
                .url(ServerAddress + "page=1")
                .cacheControl(CacheControl.FORCE_NETWORK)
                .build();

        Response response;
        try {
            response = client.newCall(request).execute();
            ou_response = response.body().string();
            response.body().close();
            if (ou_response != null) {
                try {
                    JSONObject postObj = new JSONObject(ou_response);
                    JSONArray postsArray = postObj.optJSONArray("posts");
                    infoModels = new ArrayList<>();

                    for (int i = 0; i <= infoModels.size(); i++) {
                        JSONObject postObject = (JSONObject) postsArray.get(i);
                        JSONObject images = postObject.optJSONObject("thumbnail_images");
                        JSONObject imagesPair = images.optJSONObject("medium");

                        int id = postObject.getInt("id");
                        String title = postObject.getString("title");
                        String content = postObject.getString("content");
                        String thumbnail = imagesPair.getString("url");
                        Log.d("Data", "Post id: " + id);
                        Log.d("Data", "Post title: " + title);
                        Log.d("Data", "Post title: " + thumbnail);

                        //Use the title and id as per your requirement
                        responseData.add(new MainDataModel(id, title, content, thumbnail));
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return responseData;
    }

    @Override
    protected void onPostExecute(List<MainDataModel> result) {
        CustomProcessDialog.dissmis();
        dataModels.addAll(result);


            mAdaper = new MainAdapter2(Main_page.this, main_recyclerView, dataModels);
            main_recyclerView.setAdapter(mAdaper);

    }
}
}

使用您的适配器类而不进行任何编辑,并且不要使用EventBus。