我正在创建一个具有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模式。
对此有任何解决方案吗?
答案 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
}
});