我已经看到了两个在应用程序中实例化新Fragment的一般实践:
Fragment newFragment = new MyFragment();
Run Code Online (Sandbox Code Playgroud)
和
Fragment newFragment = MyFragment.newInstance();
Run Code Online (Sandbox Code Playgroud)
第二个选项使用静态方法newInstance(),通常包含以下方法.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
Run Code Online (Sandbox Code Playgroud)
起初,我认为主要的好处是我可以重载newInstance()方法以在创建Fragment的新实例时提供灵活性 - 但我也可以通过为Fragment创建重载构造函数来实现这一点.
我错过了什么?
一种方法比另一种方法有什么好处?还是只是好习惯?
我可以savedInstanceState()在删除片段时使用保存状态,然后在从后端堆栈弹出片段时恢复状态吗?当我从后台堆栈恢复片段时,savedInstanceState包始终为null.
现在,app流程是:创建片段 - >删除片段(添加到后台堆栈) - >从后台堆栈恢复的片段(savedInstanceState bundle为null).
这是相关代码:
public void onActivityCreated(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = getArguments();
Long playlistId = bundle.getLong(Constants.PLAYLIST_ID);
int playlistItemId = bundle.getInt(Constants.PLAYLISTITEM_ID);
if (savedInstanceState == null) {
selectedVideoNumber = playlistItemId;
} else {
selectedVideoNumber = savedInstanceState.getInt("SELECTED_VIDEO");
}
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(Constants.SELECTED_VIDEO, selectedVideoNumber);
}
Run Code Online (Sandbox Code Playgroud)
我认为问题是onSavedInstanceState()当被删除并被添加到后台堆栈时永远不会被调用.如果我不能使用onsavedInstanceState(),还有另一种方法来解决这个问题吗?
我对内存泄漏以及可能导致它们的原因有基本的了解。这就是为什么我不明白我的代码是否有问题或者是误报。由于项目不小,不知道该分享哪一部分代码。但请在评论中告诉我,我会添加所需的代码。
我使用导航拱组件并遵循 MVVM 模式。我后来在项目开发中添加了 LeakCanary 库,当我在屏幕之间导航时,它立即开始向我发出有关保留实例的警告。
当我将片段添加到后堆栈时会出现问题。随着每个添加到返回堆栈的片段,保留实例的计数器增加。当达到阈值 5 LeakCanary 转储堆并提供报告。
但是,如果我单击后退按钮并返回到之前的屏幕,则保留实例的计数器会减少,最终,当返回到第一个屏幕时,所有保留的实例都会消失。
如果我查看堆分析报告,它说作为对CoordinatorLayoutin xml的引用的变量 coordinatorLayout已经泄漏。如果我删除变量及其所有用法并再次运行应用程序,我会看到同样的问题,但现在另一个变量是对 xml 中另一个视图的引用。我试图删除 LeakCanary 报告为泄漏的所有视图及其使用情况。当它说 aTextView只是用来设置文本onViewCreated而不在其他任何地方使用时,它正在泄漏,我开始怀疑我的代码中存在问题。
我分析了片段中的生命周期方法调用,并注意到当我导航到前一个片段的新屏幕时,所有方法直到和包括onDestroyView被调用但没有被调用onDestroy。当我单击返回时onDestroy,会为位于后堆栈顶部的片段调用返回,并且保留实例计数器减少。
我怀疑导航组件在返回堆栈中时保留了片段的实例,而 LeakCanary 将其视为泄漏。
android memory-leaks kotlin leakcanary android-architecture-navigation
我有几个片段可以替代另一个片段.这些片段的UI发生了变化,我需要保持它的新状态.因此代码看起来非常简单:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
if (mStepTwo == null) {
mStepTwo = new QuizStepTwo();
mStepTwo.setListener(mStepTwoListener);
} else {
fragmentTransaction.remove(mStepTwo);
}
fragmentTransaction.replace(R.id.step_holder, mStepTwo);
fragmentTransaction.addToBackStack("second_step");
fragmentTransaction.commit();
Run Code Online (Sandbox Code Playgroud)
然而,当我用第一步替换第二步时,例如按下后退按钮, - 它的'UI状态回滚到初始状态.
我如何保持国家?OnSaveInstanceState?还是更舒服的东西?
我正在构建一个简单的应用程序,我想通过物理按钮从片段回到活动.我怎么做?我试图杀死片段,但它无法正常工作.
我试图了解使用片段保存和恢复状态的过程。我用它创建了滑动导航菜单。
在其中一个片段中有这样的代码:
public class FifthFragment extends Fragment {
CheckBox cb;
View view;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fifth_layout, container, false);
cb = (CheckBox) view.findViewById(R.id.checkBox);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// Restore save state
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save state
}
}
Run Code Online (Sandbox Code Playgroud)
例如,我想在用户退出片段之前保存复选框的状态,并在再次创建片段时恢复它。如何实现这一目标?
编辑:
根据 raxellson 的回答,我已将片段更改为:
public class FifthFragment extends Fragment {
private static final …Run Code Online (Sandbox Code Playgroud) 我在片段"A"调用中从服务器获取数据.当我用"B"替换"A"时,从"B"返回"A"后,每次调用片段"A",因此每次都会生成HTTPGET.如何避免这种情况并在活动中重用像REORDER_TO_FRONT这样的片段?
我正在使用此代码替换新片段
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.rl_fragment_content, newFragment,
backStackName);
transaction.addToBackStack(backStackName);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
Run Code Online (Sandbox Code Playgroud)
当我背压时,
Fragment fragment = null;
fragment = getSupportFragmentManager().findFragmentByTag(
"some_fragment_name");
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.rl_fragment_content, fragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.addToBackStack("some_fragment_name");
transaction.commit();
Run Code Online (Sandbox Code Playgroud) android ×7
android-architecture-navigation ×1
back-stack ×1
bundle ×1
kotlin ×1
leakcanary ×1
memory-leaks ×1
savestate ×1