按下后退按钮时正在重新创建 Listview 片段
Posted
技术标签:
【中文标题】按下后退按钮时正在重新创建 Listview 片段【英文标题】:Listview fragment is getting recreated on pressing backbutton 【发布时间】:2014-04-30 15:11:14 【问题描述】:我在我的ListView
片段中使用了加载器,它在按下“返回”按钮时被重新创建。你能告诉我如何处理这种情况吗?
这是我的ListView
片段代码。在这里,我有一个布尔变量,我在单击列表项时将其设置为true
。但是一旦按下后退按钮onCreateView
将被调用,因此后退按钮将为假。
public class GTFragment extends SherlockFragment implements LoaderCallbacks<Cursor>
ListView mTListview = null;
GoogleTasksAdapter mGTasksAdapter = null;
private SQLiteCursorLoader mTLoader=null;
private LoaderManager mTLoaderManager;
private String mSelectedListID = null;
private boolean mIsBackbuttonisPressed = false;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
View view = inflater.inflate(R.layout.task_home_activity, container, false);
if(!mIsBackbuttonisPressed)
getLoaderManager().initLoader(0, null, this);
mTListview = (ListView) view.findViewById(R.id.id_task_list_home_activity);
mGTasksAdapter = new GoogleTasksAdapter(getActivity());
mTListview.setOnItemClickListener(new OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> listview,
View clickedview, int position, long arg3)
// TODO Auto-generated method stub
GoogleTaskItem item = new GoogleTaskItem();
Cursor coursor = ((GoogleTasksAdapter)listview.getAdapter()).getCursor();
if(coursor.moveToPosition(position))
mIsBackbuttonisPressed = true;
GoogleTaskController.get_googletask_controllerObj()
.LaunchTaskPreviewActivity();
);
mTListview.setAdapter(mGTasksAdapter);
mIsBackbuttonisPressed = false;
return view;
我的片段活动类代码
public class TLActivity extends SherlockFragmentActivity
LeftSliderTaskListOptions mTaskOptionsFragment = null;
GoogleTasksFragment mTFragment = null;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
setContentView(R.layout.layout_gt_list);
// FragmentTransaction tfragment = this.getSupportFragmentManager().beginTransaction();
mTFragment = new GTasksFragment();
t.replace(R.id.id_tfragment, mTFragment);
t.commit();
【问题讨论】:
@NehaShukla,当你编辑帖子时,你应该尽可能地改进它。你在开头留下了几个错别字和明显的enter code here
。
是的,你对..会小心的
@NehaShukla,谢谢 :)
【参考方案1】:
而不是
t.replace(R.id.id_tfragment, mTFragment);
使用
t.add(R.id.id_tfragment, mTFragment);
它对我有用
【讨论】:
【参考方案2】:我不认为接受的答案是正确的,因为 Fragment.onSaveInstanceState
在托管它需要保存其状态的活动之前不会被调用:docs 状态:
在很多情况下,片段可能大部分被拆除 (例如在没有显示 UI 的情况下放置在后堆栈上时),但它的 直到它拥有的活动实际上需要保存状态才会被保存 保存它的状态。
换句话说:如果您使用的 Activity 每个屏幕都有多个片段(这很常见),那么当您移动下一个屏幕时片段状态将不会被保存。
您也不能使用Fragment.setRetainInstance
,因为他只适用于不在后台堆栈中的片段。
大多数时候,您不必考虑这一点,但有时它很重要。就像您滚动列表并想要“记住”滚动位置一样。
我花了很长时间才意识到放在后堆栈上的片段是一种保存的,您可以重用您已经创建的视图,而不是每次片段调用 onCreateView 时都创建一个。我的设置是这样的:
public abstract class BaseFragment extends Fragment
private boolean mSaveView = false;
private SoftReference<View> mViewReference;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
if (mSaveView)
if (mViewReference != null)
final View savedView = mViewReference.get();
if (savedView != null)
if (savedView.getParent() != null)
((ViewGroup) savedView.getParent()).removeView(savedView);
return savedView;
final View view = inflater.inflate(getFragmentResource(), container, false);
mViewReference = new SoftReference<View>(view);
return view;
protected void setSaveView(boolean value)
mSaveView = value;
public class MyFragment extends BaseFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
setSaveView(true);
final View view = super.onCreateView(inflater, container, savedInstanceState);
ListView placesList = (ListView) view.findViewById(R.id.places_list);
if (placesList.getAdapter() == null) // this check is important so you don't restart your adapter
placesList.setAdapter(createAdapter());
【讨论】:
【参考方案3】:您有多种选择来纠正此问题。
像这样覆盖 onSaveInstanceState:
@Override
public void onSaveInstanceState (Bundle outState)
super.onSaveInstanceState(outState);
outState.putBoolean("mIsBackbuttonisPressed", mIsBackbuttonisPressed);
然后在您的 onCreateView 中,您可以通过以下方式取回您的变量:
if (savedInstanceState != null)
mIsBackbuttonisPressed = savedInstanceState.getBoolean("mIsBackbuttonisPressed", false);
您可以在片段的 onCreate 方法中设置this.setRetainInstance(true);
。
如果您可以通过创建片段发布您的活动代码,我还可以告诉您其他选项。 (PS 我不能把它写成评论,所以把它贴在答案里。)
【讨论】:
嗨,谢谢你的回答,当我按下后退按钮时,我的整个片段活动本身正在重新创建,我会给你提供片段活动的完整代码。 您好代码已更新,请您帮忙。我在单击任务列表项时创建新活动。一旦我回击,我注意到我的片段活动正在重新创建,我认为它是错误的,不知道是什么错误,如果我可以避免这种情况,那么我的问题将得到解决,希望如此。你能给我建议吗 你能检查一下在你按下后是否调用了 TLActivity onCreate 吗?原因可能是系统正在破坏您的活动。 Documentation 谢谢,我非常接近解决方案,还有一个问题,如果我按下后退按钮,那么我是否必须重新加载列表视图上的光标?信息不会存储在缓存中吗? 是的,您必须在 onCreate 中重新加载光标,因为如果 Activity 或 Fragment 被销毁,那么适配器也必须重新加载。以上是关于按下后退按钮时正在重新创建 Listview 片段的主要内容,如果未能解决你的问题,请参考以下文章
替换两个不同的片段后,按下后退按钮时会重新创建第一个片段