- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我一直在使用这种模式。这是一个非常人为的 AsyncTask + 进度指示器示例:
new AsyncTask<Void, Void, Void>() {
WeakReference<MyFragment> weakFragment = new WeakReference<MyFragment>(MyFragment.this);
@Override
protected void onPreExecute() {
Fragment fragment = weakFragment.get();
if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.VISIBLE);
}
@Override
protected Document doInBackground(Void... params) {
Fragment fragment = weakFragment.get();
if(fragment == null) return null;
// Do something ...
}
@Override
protected void onPostExecute() {
Fragment fragment = weakFragment.get();
if(fragment != null) fragment.getView().findViewById(R.id.progress).setVisibility(View.GONE);
}
}.execute();
它在方向更改时工作正常,但是当我从后台弹出 fragment 时,我注意到 fragment 是非空的并且 fragment.getView() 是空的。这显然会导致崩溃。你们使用什么方法?我似乎无法在网上找到完美的解决方案。重要说明,这是在 fragment 中,我在其 onActivityCreated(...) 中对该 fragment 调用 setRetainInstance(true);
。
最佳答案
AsyncTask
是一个异步任务,这意味着您通常不知道它何时完成以及何时调用 onPostExecute()
。 .我认为你的问题就在这里。当你旋转你的设备时,你的异步任务还没有完成,你的 fragment View 被销毁并很快重新创建,而异步任务仍然在工作线程上,当它完成它的工作时,你的 fragment 有一个 View 和 getView
的返回值不是 null
.但是如果旋转时间很长,你会得到 null
因为AsyncTask
已完成,但您的 fragment 没有任何 View 。现在这种情况恰好发生在你的后台当你将你的 fragment 推到后台时,它的 View 被销毁(look at the picture)但 fragment 本身没有( fragment 从后台返回到布局)。现在你的 AsyncTask
完成并调用您的 fragment
getView
方法,它没有任何 view
所以你会得到NPE
.
我的解决方案:
首先你应该使用WeakReference<ProgressBar>
而不是 WeakReference<MyFragment>
在onPostExecute()
检查它是否为 null,如果为 null,则什么也不做,因为如果它不是 null,则默认值是不可见的调用 setVisibility(View.GONE)
.
更新:
the fragment is alive but the view has been dealloc'd. Is this possible?
是的,只需查看链接中的图 2。当 fragment 处于 Activity 状态时(绿色框)the fragment added to back stack
fragment 转到 onPause
, onStop
onDestroyView。然后,当 fragment 从返回堆栈中弹出时,它会直接转到 onCreateView
。带有此文本的箭头链接:the fragment returns to the layout from backstack
.
为了确认我的回答,您可以创建一个 AsyncTask
并调用SystemClock.sleep(30000)
在你的里面doInbackground
.现在您可以毫无异常(exception)地将您的 fragment 插入后台堆栈并将其从后台堆栈弹出,因为 asynctask 尚未完成以及何时调用 onPostExecute()
。您的 fragment 已经有一个 View 。
您可以看到的另一个好东西是 setRetainInstance
This can only be used with fragments not in the back stack.
因此,当您将 fragment 插入后退堆栈时,它可能会完全销毁,而您可能会在弹出时获得新的 fragment 引用。但是当你使用 setRetainInstance(true);
对于配置更改,您的 fragment 在 Activity 重新创建时保留,这意味着它是相同 fragment 和onCreate
没有被调用。这是一件非常非常重要的事情,因为如果你开始你的 AsyncTask
在 onCreate
方法,当您将 fragment 插入后退堆栈并将其弹出时,您可能有一个新 fragment ,这意味着 onCreate
方法运行,另一个 AsyncTask
被解雇了。这意味着您无法控制调用 AsyncTask
的号码。所以要当心内存泄漏!
关于android - AsyncTask、Fragments、Views 和 Backstacks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26432439/
我今天在我的 Android 项目中遇到了一个涉及 aSyncTasks 的问题,经过一些研究找到了答案,并且与我交谈过的人都没有意识到,所以我想我会与 SO 社区分享,以防万一有人发现它有任何用处。
我目前正在 AsyncTask 的 onPostExecute 方法中执行类似的操作,其中 NewTask 不是当前正在执行的任务: private class OlderTask extends A
所以,我正在研究一个条形码解码器,一旦我们有了条形码,它就会通过互联网进入多个 API 来解码刚刚扫描的内容。问题是我必须将一些 XML 解析链接在一起,我不知道我做的是否正确。 因此,扫描条形码后,
我的团队开发了一个新的 Android 应用程序,它广泛使用了 Room。 我不确定我们是否正确使用 AsyncTask。 我们不得不在 AsyncTasks 中包装所有对 insert/update
我查看了其他问题,但未能澄清我对从另一个任务调用任务的疑问,我有以下代码: protected List doInBackground(String... params) try {
我正在开发一个访问 Web 服务的应用程序,并使用从中获取的 JSON 创建一个对象并在我的代码中使用它。尽管我的应用程序正在运行,但我不知道它是否写得很好且完美无缺。 我将解释我的内容,然后放置一些
虽然我还没有尝试过,但从理论上讲,我问这个问题只是为了消除我的疑虑。 我有这样一个场景:1. 向服务器发送请求并接收 JSON 响应。为此,我正在使用 AsyncTask,因为接收响应可能会有延迟。2
我有以下 AsyncTask 的实现,允许多个 AsyncTask 同时运行: public abstract class MyAsyncTask extends AsyncTask { pu
花了很多时间试图解决这个问题,我已经阅读了很多问题、论坛、答案......但它仍然不会更新 UI。 我的最终目标是从用户那里获取一个搜索词,并将一个 httprequest 发送到用 JSON 回复的
我有一个异步任务 private class LoadData extends AsyncTask { private String WEBURL; LoadData(String u
我正在用 android 做一些编码工作。我几乎遇到了一个问题,为了解决这个问题,我需要一个匿名 AsyncTask 类来执行。但我还需要在执行之前传递并反对这个类。我尝试了下面的代码,但它不起作用,
我有两个 AsyncTask:第一个寻找素数,如果成功,我必须调用第二个 AsyncTask 显示单词“Yop!” (将这个词添加到数组列表中,并显示在AsyncTask三)。 如果我从 onProg
我想使用 AsyncTask 将图像加载到 ListView。 private class LoadImageTask extends AsyncTask,Void,Bitmap>{ @Sup
在我的 AsyncTask 的某个时刻,在完成一些验证之后,我需要派生另一个线程来做一些其他工作。所以我现在想要两个后台线程,每个都做自己的事情(每个执行大约 2-3 秒)。我们的想法是最大限度地提高
(这与空指针无关):我在 AsyncTask 中有一个进度条,并且添加了一个取消按钮来取消 asynctask。 我可以从异步任务外部取消异步任务,但我需要在异步任务下实现的progressdialo
我有一个 Activity ,在启动时调用“json”来获取歌曲的数据类别,之后我调用方法“AsyncTask”来获取来自另一个“JSON”的歌曲列表问题是,当我启动 Activity 时,它被锁定,
我想做以下事情。我想显示一个包含信息和图像的列表。这些图像需要一段时间才能加载,所以我想我会采取不同的方式。我会使用两个 AsyncTasks。第一个创建所有布局并用除图像之外的数据填充它。第二个只是
如果我做了这样的事情: public class MyFragment extends Fragment { private GetDataTask mGDT; //onCreat
在 Android Activity 中,我在 onCreate 方法中执行 AsyncTask。我应该在 AsyncTask 的 onPostExecute 中还是在 OnCreate 方法中声明
我对 AsyncTask 有疑问我尝试为 10 个 Json 文件向互联网打开 10 个请求,因此我读取它并将其保存到用户设备_由于数据差异,此文件必须分开,包括。 那么,将每个请求放在单个 Asyn
我是一名优秀的程序员,十分优秀!