我遇到了片段的内存问题,我可以使用一些帮助来获取适当的路径。我不能使用简单的backstack,因为应用程序需要保留用户在应用程序中使用的多个路径(并且用户可以来回跳转)。导航以这种方式处理片段:
transaction.hide(currentFragment).show(newFragment).commit();
我认为这有助于我的情况是暂时销毁片段的视图,然后在片段放回视图时重新创建(而不是简单地从用户的视图中隐藏UI)。从阅读API,它听起来不像hide方法这样做。有没有人知道FragmentTransaction / FragmentManager / Fragment类是否有一些内置方法可以让我这样做?
我正在考虑的另一个选择是为每个片段创建自己的生命周期。我也探索过使用tabhost,但它似乎没有解决内存问题。如果你有另一个想法,我愿意接受它。
谢谢大家,感谢您对此的帮助。
答案 0 :(得分:0)
我想出了一个解决方案来实现更好的内存管理解决方案(基于适配器),同时保存多个用户旅程(独立选项卡包含代表backstack的东西)。我使用FragmentManager报废,因为它不利于这种行为。我将在这里留下我的答案以防万一其他人遇到类似的问题,需要使用带有FragmentStatePagerAdapter的ViewPagers的多个反向堆栈 - 一个viewpager用于他们应用程序中的每个选项卡(这仍然可以清理更多,但你可以获得jist) :
主要活动:
public class MultiTabbedActivity extends FragmentActivity implements NavigationFragment.OnNavigationSelectedListener
{
private Page1Fragment mPage1;
private Page2Fragment mPage2;
private CustomFragment mCurrent;
private String mNav;
private List<CustomFragment> mPage1BackStack;
private List<CustomFragment> mPage2BackStack;
private CustomViewPager mPagerPage1;
private CustomViewPager mPagerPage2;
private boolean mUpdating = false;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// initialize the backstacks
mPage1BackStack = new ArrayList<CustomFragment>();
mPage2BackStack = new ArrayList<CustomFragment>();
mPage1 = new Page1Fragment();
mPage2 = new Page2Fragment();
mPage1BackStack.add(mPage1);
mPage2BackStack.add(mPage2);
mPagerPage1 = (CustomViewPager) findViewById(R.id.page1_fragment);
mPagerPage2 = (CustomViewPager) findViewById(R.id.page2_fragment);
mPagerPage1.setOffscreenPageLimit(3); //Customizable to determine how many
mPagerPage2.setOffscreenPageLimit(3); //fragments you want to hold in memory
mPagerPage1.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage1BackStack));
mPagerPage2.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage2BackStack));
displayPager(mPagerPage1);
mCurrent = mPage1;
mNav = GlobalConstants.PAGE_PAGE1;
}
private void displayPager(ViewPager pager)
{
mPagerPage1.setVisibility(ViewPager.GONE);
mPagerPage2.setVisibility(ViewPager.GONE);
pager.setCurrentItem(pager.getAdapter().getCount() - 1);
pager.getAdapter().notifyDataSetChanged();
pager.setVisibility(ViewPager.VISIBLE);
}
@Override
public void onNavSelected(String page)
{
if (page != null && page != "" && !mUpdating)
{
// Determine the Fragment selected
if (page.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
{
mNav = GlobalConstants.PAGE_PAGE1;
displayPager(mPagerPage1);
mCurrent = mPage1BackStack.get(mPage1BackStack.size() - 1);
}
else if (page.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
{
mNav = GlobalConstants.PAGE_PAGE2;
displayPager(mPagerPage2);
mCurrent = mPage2BackStack.get(mPage2BackStack.size() - 1);
}
}
}
@Override
public void onBackPressed()
{
PageFragment navFrag = null;
// Update the Navigation Menu to indicate the currently visible
// Fragment
try
{
mUpdating = true;
if (mPage1BackStack.size() > 1 && mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
{
mPagerPage1.setCurrentItem(mPage1BackStack.size() - 2);
mPage1BackStack.remove(mPage1BackStack.size() - 1);
navFrag = mPage1BackStack.get(mPage1BackStack.size() - 1);
mPagerPage1.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage1BackStack));
}
else if (mPage2BackStack.size() > 1 && mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
{
mPagerPage2.setCurrentItem(mPage2BackStack.size() - 2);
mPage2BackStack.remove(mPage2BackStack.size() - 1);
navFrag = mPage2BackStack.get(mPage2BackStack.size() - 1);
mPagerPage2.setAdapter(new CustomFragmentAdapter(getSupportFragmentManager(), mPage2BackStack));
}
else
{
super.onBackPressed();
}
if (navFrag != null)
mCurrent = navFrag;
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
mUpdating = false;
}
}
public void updateFragment(PageFragment newFragment)
{
if (mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE1))
{
mPage1BackStack.add(newFragment);
displayPager(mPagerPage1);
}
else if (mNav.equalsIgnoreCase(GlobalConstants.PAGE_PAGE2))
{
mPage2BackStack.add(newFragment);
displayPager(mPagerPage2);
}
mCurrent = newFragment;
}
}
CustomViewPager:
public class CustomViewPager extends ViewPager {
private boolean enabled;
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
CustomAdapter:
public class CustomFragmentAdapter extends FragmentStatePagerAdapter
{
List<CustomFragment> mFragments;
public CustomFragmentAdapter(FragmentManager fm, List<CustomFragment> fragments)
{
super(fm);
mFragments = fragments;
}
public List<PageFragment> getmFragments()
{
return mFragments;
}
public void setmFragments(List<CustomFragment> mFragments)
{
this.mFragments = mFragments;
}
@Override
public int getCount()
{
return mFragments.size();
}
@Override
public Fragment getItem(int position)
{
return (Fragment) (mFragments.get(position));
}
}
UI(包裹在线性布局中):
<fragment
android:id="@+id/navigation_fragment"
android:name="your.package.here.NavigationFragment"
android:layout_width="70dp"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/page_fragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="2" >
<your.package.here.CustomViewPager
android:id="@+id/page1_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<your.package.here.CustomViewPager
android:id="@+id/page2_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>