Android - 在 UI 片段中保留对象
Android - Retain objects in UI Fragment
在我的项目中,我最初使用的是这个方案:
Activity A
(UI) > Fragment B
(non-UI) > Adapter + AsyncTask
B
与 setRetainInstance(true)
一起保留并更新 A
UI
A
用 getFragmentManager()
实例化 B
但是我现在需要用到UI分片,所以想到了这个方案:
Activity A
> Fragment B
(UI) > Fragment C
(non-UI) > Adapter + AsyncTask
C
与 setRetainInstance(true)
一起保留并更新 B
UI
B
用 getChildFragmentManager()
实例化 C
不过好像不行:
Caused by: java.lang.IllegalStateException:
Can't retain fragements that are nested in other fragments
我试图用 getFragmentManager()
而不是 getChildFragmentManager()
来实例化 C
但我遇到了一些问题。
在 Fragment 中保留对象和管理 AsyncTask 的最佳做法是什么?
终于开发出小帮手了class:
public class RetainFragment<F extends Fragment> extends Fragment {
private static <F extends Fragment> String tag(F ui, Object id) {
return ui.getClass().getName() + id.toString();
}
public static <F extends Fragment> Fragment get(F ui, Object id) {
return ui.getFragmentManager().findFragmentByTag(tag(ui, id));
}
public F ui;
public Object id;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
setRetainInstance(true);
}
public void link(F ui, Object id) {
this.id = id;
this.ui = ui;
if (get(ui, id) == null) {
ui.getFragmentManager()
.beginTransaction()
.add(this, tag(ui, id))
.commit();
}
}
public void unlink() {
if (get(ui, id) != null) {
ui.getFragmentManager()
.beginTransaction()
.remove(this)
.commit();
}
ui = null;
id = null;
}
}
而现在,在 UI 个片段中,我只写:
public class UiFragment extends Fragment {
private static class Retain extends RetainFragment<UiFragment> {
private MyAsyncTask task; // Objects to retain over
private MyAdapter adapter; // configuration changes
}
private Retain retain;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
retain = (Retain) Retain.get(this, 0);
if (retain == null) {
retain = new Retain();
// Retained objects initialization
retain.adapter = new MyAdapter();
}
retain.link(this, 0);
}
@Override
public void onDetach() {
if (isRemoving()) {
// Retained objects terminate
if (retain.task != null) {
retain.task.cancel(true);
}
retain.unlink();
}
super.onDetach();
}
private void update() {
if (!isDetached()) {
// Update UI fragment
}
}
}
在retain.task.onPostExecute()
中:
retain.ui.update(); // Reference to the last ui fragment instance linked
并在 UI 片段启动时启动任务:
private static class Retain extends RetainFragment<UiFragment> {
private MyAsyncTask task; // Objects to retain over
private MyAdapter adapter; // configuration changes
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
ui.onRetainCreated();
}
}
private void onRetainCreated() {
retain.task = new MyAsyncTask() {
@Override
protected void onPostExecute(Void result) {
retain.ui.update();
}
};
retain.task.execute();
}
在我的项目中,我最初使用的是这个方案:
Activity
A
(UI) > FragmentB
(non-UI) > Adapter + AsyncTask
B
与setRetainInstance(true)
一起保留并更新A
UIA
用getFragmentManager()
实例化
B
但是我现在需要用到UI分片,所以想到了这个方案:
Activity
A
> FragmentB
(UI) > FragmentC
(non-UI) > Adapter + AsyncTask
C
与setRetainInstance(true)
一起保留并更新B
UIB
用getChildFragmentManager()
实例化
C
不过好像不行:
Caused by: java.lang.IllegalStateException:
Can't retain fragements that are nested in other fragments
我试图用 getFragmentManager()
而不是 getChildFragmentManager()
来实例化 C
但我遇到了一些问题。
在 Fragment 中保留对象和管理 AsyncTask 的最佳做法是什么?
终于开发出小帮手了class:
public class RetainFragment<F extends Fragment> extends Fragment {
private static <F extends Fragment> String tag(F ui, Object id) {
return ui.getClass().getName() + id.toString();
}
public static <F extends Fragment> Fragment get(F ui, Object id) {
return ui.getFragmentManager().findFragmentByTag(tag(ui, id));
}
public F ui;
public Object id;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
setRetainInstance(true);
}
public void link(F ui, Object id) {
this.id = id;
this.ui = ui;
if (get(ui, id) == null) {
ui.getFragmentManager()
.beginTransaction()
.add(this, tag(ui, id))
.commit();
}
}
public void unlink() {
if (get(ui, id) != null) {
ui.getFragmentManager()
.beginTransaction()
.remove(this)
.commit();
}
ui = null;
id = null;
}
}
而现在,在 UI 个片段中,我只写:
public class UiFragment extends Fragment {
private static class Retain extends RetainFragment<UiFragment> {
private MyAsyncTask task; // Objects to retain over
private MyAdapter adapter; // configuration changes
}
private Retain retain;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
retain = (Retain) Retain.get(this, 0);
if (retain == null) {
retain = new Retain();
// Retained objects initialization
retain.adapter = new MyAdapter();
}
retain.link(this, 0);
}
@Override
public void onDetach() {
if (isRemoving()) {
// Retained objects terminate
if (retain.task != null) {
retain.task.cancel(true);
}
retain.unlink();
}
super.onDetach();
}
private void update() {
if (!isDetached()) {
// Update UI fragment
}
}
}
在retain.task.onPostExecute()
中:
retain.ui.update(); // Reference to the last ui fragment instance linked
并在 UI 片段启动时启动任务:
private static class Retain extends RetainFragment<UiFragment> {
private MyAsyncTask task; // Objects to retain over
private MyAdapter adapter; // configuration changes
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
ui.onRetainCreated();
}
}
private void onRetainCreated() {
retain.task = new MyAsyncTask() {
@Override
protected void onPostExecute(Void result) {
retain.ui.update();
}
};
retain.task.execute();
}