AsyncTask的doInBackground方法中AsyncObj对象为空问题求助
嘿,我之前也遇到过类似的AsyncTask成员变量突然为空的问题,结合你的代码和描述,咱们梳理几个最可能的原因和对应的解决方式:
1. 线程可见性问题(概率最高)
你在主线程的构造函数里给asyncObj1赋了值,但doInBackground是在后台线程跑的——Java里如果变量没加volatile修饰,后台线程可能看不到主线程的赋值操作,读取到的还是默认的null。这是因为JVM可能会对变量做缓存或者指令重排,导致线程间的变量不可见。
解决办法:
给asyncObj1加上volatile修饰符,强制线程间的变量可见:
class SendHttp extends AsyncTask<Void,Void,Void> { private volatile AsyncObj asyncObj1; // 加上volatile SendHttp(AsyncObj asyncObj){ this.asyncObj1 = asyncObj; Log.v("TAG","In constructor: "+asyncObj1.valuesX.size()); } // 剩下的代码保持不变 }
2. AsyncTask实例没被正确持有,被GC回收了
如果你的SendHttp是在某个方法里临时创建的局部变量(比如直接在按钮点击方法里new SendHttp(obj).execute()),那方法执行完之后,这个AsyncTask实例就可能被垃圾回收器收走,连带asyncObj1也变成null。
解决办法:
把SendHttp变成Activity的成员变量,让它的生命周期和任务执行周期对齐,顺便在Activity销毁时取消任务,还能避免内存泄漏:
public class YourActivity extends AppCompatActivity { private SendHttp sendHttpTask; // 用成员变量持有 // 启动任务的方法 private void startHttpTask() { AsyncObj obj = new AsyncObj(valuesX, valuesY, valuesZ); sendHttpTask = new SendHttp(obj); sendHttpTask.execute(); } @Override protected void onDestroy() { super.onDestroy(); // 销毁前取消任务,防止内存泄漏 if (sendHttpTask != null && !sendHttpTask.isCancelled()) { sendHttpTask.cancel(true); } } }
3. 原ArrayList被意外修改了(可能性较低,但可以排查)
因为AsyncObj里的三个集合是对原ArrayList的引用,如果你在创建AsyncObj并传给SendHttp之后,在主线程把原集合clear()或者设为null了,虽然asyncObj1本身不为空,但集合会变成空。不过你说的是AsyncObj对象为空,这个可能性不大,但可以检查一下相关代码。
解决办法:
如果要避免原集合的修改影响AsyncTask,就在AsyncObj的构造函数里创建集合的副本:
public class AsyncObj { ArrayList<Float> valuesX; ArrayList<Float> valuesY; ArrayList<Float> valuesZ; public AsyncObj(ArrayList<Float> a, ArrayList<Float> b, ArrayList<Float> c) { // 复制原集合,切断引用关联 this.valuesX = new ArrayList<>(a); this.valuesY = new ArrayList<>(b); this.valuesZ = new ArrayList<>(c); } }
4. 配置变更导致Activity重建(比如屏幕旋转)
如果在AsyncTask执行的时候,你旋转了屏幕,Activity会被销毁重建,旧的AsyncTask持有的是旧Activity的引用,asyncObj1可能跟着旧Activity被回收,变成null。
解决办法:
要么用ViewModel来保存AsyncObj的状态,要么在Manifest里给Activity加个属性,禁止它因为屏幕旋转重建:
<activity android:name=".YourActivity" android:configChanges="orientation|screenSize"> </activity>
内容的提问来源于stack exchange,提问作者Vitto Russo

