先说明一下原理:
1.利用反射机制获取 RequestQueue 队列中 mCurrentRequests 当前请求的集合,如果size==0, 则说明并发性网络请求已完成,为了保证准确性,建议给需要监听的网络请求设置tag,并利用tag进行过滤
2.利用定时循环线程进行动态取值
代码如下:
public static void whetherRequestCompleted(Context context,RequestSchedule requestSchedule){ whetherRequestCompleted(context,null,requestSchedule); } public static void whetherRequestCompleted(final Context context, final Object requestTag, final RequestSchedule requestSchedule){ final Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==0){ requestSchedule.completed(); }else if(msg.what==1){ requestSchedule.failed((Exception)msg.obj); } } }; final Timer timer = new Timer(); timer.schedule(new TimerTask() { int num = 0; public void run() { try { ++this.num; boolean e = true; RequestQueue requestQueue = VolleyManager.getRequestQueue(context); Field field = requestQueue.getClass().getDeclaredField("mCurrentRequests"); field.setAccessible(true); Set set = (Set)field.get(requestQueue); if(set!=null&&set.size()>0){ Iterator var5 = set.iterator(); while(var5.hasNext()) { Request r = (Request)var5.next(); if(r!=null&&r.getTag()!=null){ if(r.getTag().equals(requestTag == null?context.getClass().getName():requestTag)) { e = false; } } } } if(e) { Message message=new Message(); message.what=0; message.obj=null; handler.sendMessage(message); timer.cancel(); return; } if((long)(this.num * 1000) > VolleyManager.mTimeoutMs) { Message message=new Message(); message.what=1; message.obj=new TimeoutException(); handler.sendMessage(message); timer.cancel(); return; } } catch (NoSuchFieldException var7) { Message message=new Message(); message.what=1; message.obj=var7; handler.sendMessage(message); timer.cancel(); } catch (IllegalAccessException var8) { Message message=new Message(); message.what=1; message.obj=var8; handler.sendMessage(message); timer.cancel(); } catch (ConcurrentModificationException var9) { } } }, 0L, 1000L); } public interface RequestSchedule{ abstract void completed(); abstract void failed(Exception e); }
说明:
1, 第一个方法中tag==null, 本人在代码用默认使用当前页面的类名进行过滤(如果不使用,可以忽略)
2. 使用handler 是为了保证在主线程用调用回调接口可以进行UI操作
3. mTimeoutMs 是为了避免死锁问题