【问题标题】:Listview fragment is getting recreated on pressing backbutton按下后退按钮时正在重新创建 Listview 片段
【发布时间】: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,谢谢 :)

标签: android listview android-fragments android-listview adapter


【解决方案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】:

      您有多种选择来纠正此问题。

      1. 像这样覆盖 onSaveInstanceState:

        @Override
        public void onSaveInstanceState (Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putBoolean("mIsBackbuttonisPressed", mIsBackbuttonisPressed);
        }
        

        然后在您的 onCreateView 中,您可以通过以下方式取回您的变量:

        if (savedInstanceState != null)
            mIsBackbuttonisPressed = savedInstanceState.getBoolean("mIsBackbuttonisPressed", false);
        
      2. 您可以在片段的 onCreate 方法中设置this.setRetainInstance(true);

      如果您可以通过创建片段发布您的活动代码,我还可以告诉您其他选项。 (PS 我不能把它写成评论,所以把它贴在答案里。)

      【讨论】:

      • 嗨,谢谢你的回答,当我按下后退按钮时,我的整个片段活动本身正在重新创建,我会给你提供片段活动的完整代码。
      • 您好代码已更新,请您帮忙。我在单击任务列表项时创建新活动。一旦我回击,我注意到我的片段活动正在重新创建,我认为它是错误的,不知道是什么错误,如果我可以避免这种情况,那么我的问题将得到解决,希望如此。你能给我建议吗
      • 你能检查一下在你按下后是否调用了 TLActivity onCreate 吗?原因可能是系统正在破坏您的活动。 Documentation
      • 谢谢,我非常接近解决方案,还有一个问题,如果我按下后退按钮,那么我是否必须重新加载列表视图上的光标?信息不会存储在缓存中吗?
      • 是的,您必须在 onCreate 中重新加载光标,因为如果 Activity 或 Fragment 被销毁,那么适配器也必须重新加载。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多