Android ViewPager +自定义适配器延迟

时间:2017-09-20 07:14:29

标签: android listview android-fragments android-viewpager

我正在创建一个具有ViewPager的活动,而在ViewPager中有5个标签/片段。我也在实现FragmentPagerAdapter,如下所示:

public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    return fragmentA;
                case 1:
                    return fragmentB;
                case 2:
                    return fragmentC;
                case 3:
                    return  fragmentD;
                case 4:
                    return fragmentE;
                default:
                    return fragmentA;
            }
        }

        @Override
        public int getCount() {
            return numberOfPage;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return tabTitle[position];
        }
    }

上面的代码只显示片段并初始化视图而不将数据填充到listview中,将数据填充到listview中我使用下面的代码:

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

                }

                @Override
                public void onPageSelected(int position) {
                    mSectionsPagerAdapter.notifyDataSetChanged();
                    switch (position){
                        case 0:
                            fragmentA.requestDataFromServer();
                            break;
                        case 1:
                            fragmentB.requestDataFromServer();
                            break;
                        case 2:
                            fragmentC.requestDataFromServer();
                            break;
                        case 3:
                            break;
                        case 4:
                            break;
                        default:
                           break;
                    }
                }

                @Override
                public void onPageScrollStateChanged(int state) {

                }
            });
        mViewPager.setOffscreenPageLimit(4);

和requestDataFromServer():

public void requestDataFromServer(){
    new Thread(new Runnable{
        @Override
        public void run(){
            //below is volley request
            ApiServer.getInstance().requestData(getContext(),new JsonResponseCb{
                @Override
                public onSuccess(Object res){

                    new Thread(new Runnable{
                        list.addAll((List<Example>)res);
                    }).start();

                    adapter.notifyDataSetChanged();
                }
                @Override
                public onFail(Object res){}
                @Override
                public onError(Object res){}

            });
        }

    }).start();

}

requestData()代码:

public void requestData(final Context context, final JsonResponseCb cb)
    {
        LogHelper.debug(getClass(),"Outside thread = "+Thread.currentThread().getName());
        if (cb == null || context == null)
            return;
        apiServerRequest(context, Constants.getNFUrl(), null, new ApiServer.ServerCallback() {
            @Override
            public void onSuccess(final JSONObject jsonObject) {
                NfResponse response = gson.fromJson(jsonObject.toString(), NfResponse.class);
                if(response.getStatus() != null && response.getStatus().equals("OK"))
                    cb.onSuccess(response.getNewsfeedPost());
                else
                    cb.onFail(null);

            }

            @Override
            public void onError(VolleyError error) {

            }
        },Request.Method.GET);
    }

apiServerRequest()代码:

private void apiServerRequest(Context context, String url, Map<String, Object> bodyParameter, final ServerCallback serverCallback, int method) {
        final RequestQueue requestQueue = Volley.newRequestQueue(context);
        if (bodyParameter == null) {
            final JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(method, url, null, new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    serverCallback.onSuccess(response);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    serverCallback.onError(error);
                }
            });
            requestQueue.add(jsonObjectRequest);
            jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(Constants.SERVER_TIMEOUT, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        } else {
            final JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(method, url, new JSONObject(bodyParameter), new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    serverCallback.onSuccess(response);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    serverCallback.onError(error);
                }
            });
            requestQueue.add(jsonObjectRequest);
            jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(Constants.SERVER_TIMEOUT, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        }

    }

我已经运行了一个不同的线程来填充数据,但它仍然说

Skipped 31 frames!  The application may be doing too much work on its main thread.

我在listview中使用了自定义适配器,并在适配器上实现了ViewHolder模式。

对此有任何解决方案吗?

1 个答案:

答案 0 :(得分:1)

发生了什么事?

您实际上只在后台Thread上发送请求,而onSuccess回调稍后会在主Thread上运行,从而导致延迟。为了说明这一点,这里有一个小例子:

final RequestQueue q = Volley.newRequestQueue(this);
q.start();
    new Thread((new Runnable() {
        @Override
        public void run() {
            Log.w("Thread:", Thread.currentThread().getName()); // Thread-13 in my test-case
            JsonObjectRequest request = new JsonObjectRequest(
                   Request.Method.GET, 
                   "https://jsonplaceholder.typicode.com/posts/1", 
                    new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) { // <-- your onSuccess callback
                    Log.e("Thread:", Thread.currentThread().getName()); // main
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Thread:", Thread.currentThread().getName()); // main
                }
            });
            q.add(request); // roughly equivalent to your requestData call
        }
    })).start();

如何防止它发生?

您应该启动一个工作人员Thread来处理服务器响应 后得到此响应。

尝试以下方法:

public void requestData(final Context context, final JsonResponseCb cb)
{
    LogHelper.debug(getClass(),"Outside thread = "+Thread.currentThread().getName());
    if (cb == null || context == null)
        return;
    apiServerRequest(context, Constants.getNFUrl(), null, new ApiServer.ServerCallback() {
        @Override
        public void onSuccess(final JSONObject jsonObject) {
          new Thread(() -> {
            NfResponse response = gson.fromJson(jsonObject.toString(), NfResponse.class);
              if(response.getStatus() != null && response.getStatus().equals("OK"))
               cb.onSuccess(response.getNewsfeedPost());
              else
               cb.onFail(null);
      }).start();
    }

        @Override
        public void onError(VolleyError error) {

        }
    },Request.Method.GET);
}

注意在这种情况下,将在后台线程上调用onSuccess回调,并且您应该将此回调中需要执行的任何UI操作包装到

runOnUiThread(new Runnable() {
        @Override
        public void run() {
           // your UI code here
        }
    });