Android网络请求处理异步回调风险方案

     尊重原创,转载请标明出处http://blog.csdn.net/zcxwww


     我们都知道网络请求是异步的,所以就存在异步回调风险,具体来说,就是发出网络请求后,由于各种原因,如果view被回收,这时候执行回调函数就会因为找不到view而报空指针异常导致crash,而这种异步回调在我们程序中无处不在,不仅是网络请求,本地的异步任务,或者动画等都存在这种风险。可见如果不对异步回调做处理来规避这种风险,程序随时存在被crash的风险。


    而处理这个问题的总体思路,一般包括两种:

          1.管理request,即管理网络请求,不让发出去的request处在一个无法掌控的状态,这样我们就可以在view被回收的时候,统一cancel掉所有request,也就从根本上解决了网络请求异步回调的问题。

          2.如果觉得管理所有request比较复杂,还有一种方法就是在异步回调函数里对view进行判断空,如果判断到view为null,则不执行回调,这样也能解决这个问题。


    按照上面的两种思路,接下来分别给出解决方法,并给出优化的方案,不管用哪种方法,规避这种风险的最佳方案就是让写代码的人无法感知到我们已经帮他规避了这个风险,也就是不管写代码的人是否有谨慎的逻辑和好的代码风格,我们都要保证这个异步回调风险被解决,从根本上解决这个风险。


        第二种方案

        首先介绍上面说的第二种方案的解决办法,也是我最先想到和实施的办法,他可以解决网络请求异步回调的这种风险,但是也有一点小缺点,下面进行介绍:

       基于第二种方案,最先想到的肯定就是,在每次网络请求回来执行异步回调函数的里面先对view进行判空,再执行下面剩余的操作,但是这要求每个程序员都十分谨慎和自律,理论上是无法保证程序员不疏漏的,所以要在上层就解决这个问题,对后续写代码的人透明。

       1.首先我们需要维护一个Activity的栈,当Activity被创建的时候添加入栈,当Activity被finish的时候出栈,这个可以在项目的Activity的基类里实现,对下面的Activity透明。

      2.在我们的request基类里,添加一个成员变量hostAddress(所在Activity的内存地址),并提供一个setHostAddress()方法。

      3.在request基类里,实现一个判定该request所在的Activity是否被finish掉的方法isHostFinish(),这个方法里就是拿该request的hostAddress(所在Activity的内存地址),遍历Activity栈,看时候该Activity还存活。

     4.就是关键的一步了,在request基类的调用回调函数步骤之前先调用isHostAddress()来判断所在Activity是否finish,如果是则不执行回调。

    5.在Activity基类里提供一个执行网络请求的方法sendRequest(),里面除了正常的逻辑之外,还要调用request的setHostAddress()来设置所在Activity的内存地址(下面会说为什么要用内存地址,即Activity.toString()).


      基本就大功告成了,后续程序员只要调用sendRequest()方法来执行网络请求就可以规避这个问题了,接下来说说这个方法的优点和缺点。

    优点

                 1.基本解决了网络请求异步回调风险,对后续程序员透明,并封装了sendRequest(),使用简单明了。

                 2.对Activity使用的是内存地址,而不是直接传Activity对象,防止了内存泄漏问题,内存也能唯一标识一个对象。

   

    缺点

               1.上面的做法,维护一个Activity栈,显然只对Activity里的reques有效,对于Fragment里的request,如果要规避,则又要维护一个Fragment栈,显然这不是一种好的设计模式。

               2.如果放眼到整个项目的结构和分层思想来说,这显然也不是一个好的设计,因为根据单一功能原则,request里面干的事情应该很纯粹,就是发送请求,接收数据,执行回调,不应该再把Activity的地址,这些和他不相关的东西引入到这个类里,还有一些判断逻辑引入到这个类里都是不合适的。



       第一种方案

       对于上面说的方案,缺点很明显,就是由于把相关的判断逻辑引入到了request基类里,导致破坏了单一功能原则,对于整个设计来说不是一种好的方案,那就尝试上面所说的第一种方案,就是:统一管理每个Activity的request,让我们能实时控制每一个Request的状态,以便在view被回收时可以统一取消所有未完成的request.具体实现方案如下:

       1.这个方案的核心就是建立一个request管理类:requestManager,里面负责维护一个request列表,并提供把request加入这个列表,和cancel一个request和清空request列表的方法。

       2.建立一个Model类,每个model里拥有一个requestManager来管理此model里的所有request,Model里提供sendRequest()[此方法里执行网络请求,并把request添加到request队列],clear()清除request列表里的所有request,并cancel.

      3.在Activity基类里,实例化一个model,这样子也就是每个Activity拥有一个Model,每个Model拥有一个requestManager,也就是每个Activity拥有一个requst列表,并可以轻松管理这个列表。然后在Activity基类里提供sendRequest()里面调用model的sendRequest就可以了,并在Activity基类里的onDestory()里调用model的clear()方法来cancel调该Activity里的所有request.

       至此后续程序员就可以调用sendRequest()来执行网络请求,对于异步回调的处理对他们也是透明的。


      这种方案达到了我们规避网络请求异步回调的风险,并解决了上面那种方案的两个比较明显的确定,也是一种比较好的设计。


     对于网络请求的异步回调风险,上面两种方案基本能比较好的解决了。


    当然虽然说网络请求的异步回调是项目里最主要的异步回调,但是类似AsyncTask,动画等等这种异步回调也应该统一被解决,所以我预想的比较完美的方案就是设计一套统一的异步回调引擎,所有的异步回调都走这个,统一解决这个问题,关于这个,就下次再详细说了。

   

           

你可能感兴趣的:(Android开发,Android,FramWork)