gpt4 book ai didi

android - AsyncTask、Fragments、Views 和 Backstacks

转载 作者:塔克拉玛干 更新时间:2023-11-02 18:56:19 25 4
gpt4 key购买 nike

我一直在使用这种模式。这是一个非常人为的 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没有被调用。这是一件非常非常重要的事情,因为如果你开始你的 AsyncTaskonCreate方法,当您将 fragment 插入后退堆栈并将其弹出时,您可能有一个新 fragment ,这意味着 onCreate方法运行,另一个 AsyncTask被解雇了。这意味着您无法控制调用 AsyncTask 的号码。所以要当心内存泄漏!

关于android - AsyncTask、Fragments、Views 和 Backstacks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26432439/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com