Android异步请求导致crash的问题

问题分析

网络请求是异步的,发出网络请求后,如果view被回收,然后请求成功,执行回调函数就会因为找不到view而报空指针异常导致crash,而这种异步回调在是很常见的,包括网络请求,读取文件等都存在这种风险。如果不对异步回调做处理来规避这种风险,App会存在空指针然后崩溃的风险。

解决办法

1. 管理request,即管理网络请求,不让发出去的request处在一个无法掌控的状态,这样我们就可以在view被回收的时候,统一cancel掉所有request,从根本上解决网络请求异步回调的问题。
  • 首先我们需要维护一个Activity的栈,当Activity被创建的时候添加入栈,当Activity被finish的时候出栈,这个可以在项目的Activity的基类里实现,对下面的Activity透明。
  • 在我们的request基类里,添加一个成员变量hostAddress(所在Activity的内存地址),并提供一个setHostAddress()方法。
  • 在request基类里,实现一个判定该request所在的Activity是否被finish掉的方法isHostFinish(),这个方法里就是拿该request的hostAddress(所在Activity的内存地址),遍历Activity栈,看时候该Activity还存活。
  • 就是关键的一步了,在request基类的调用回调函数步骤之前先调用isHostAddress()来判断所在Activity是否finish,如果是则不执行回调。
  • 在Activity基类里提供一个执行网络请求的方法sendRequest(),里面除了正常的逻辑之外,还要调用request的setHostAddress()来设置所在Activity的内存地址(下面会说为什么要用内存地址,即Activity.toString()).

优 点 \color{#FF0000}{优点}

1.基本解决了网络请求异步回调风险,对后续程序员透明,并封装了sendRequest(),使用简单明了。
2.对Activity使用的是内存地址,而不是直接传Activity对象,防止了内存泄漏问题,内存也能唯一标识一个对象。

缺 点 \color{#FF0000}{缺点}

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

2. 在异步回调函数里对view进行判空,如果判断到view为null,则不执行回调,从而解决崩溃问题。
  • 这个方案的核心就是建立一个request管理类:requestManager,里面负责维护一个request列表,并提供把request加入这个列表,和cancel一个request和清空request列表的方法。
  • 建立一个Model类,每个model里拥有一个requestManager来管理此model里的所有request,Model里提供sendRequest()[此方法里执行网络请求,并把request添加到request队列],clear()清除request列表里的所有request,并cancel.
  • 在Activity基类里,实例化一个model,这样子也就是每个Activity拥有一个Model,每个Model拥有一个requestManager,也就是每个Activity拥有一个requst列表,并可以轻松管理这个列表。然后在Activity基类里提供sendRequest()里面调用model的sendRequest就可以了,并在Activity基类里的onDestory()里调用model的clear()方法来cancel调该Activity里的所有request.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NEU_SML

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值