Android Fragment,无需重新创建/重新加载Fragment即可返回

时间:2012-12-12 23:32:08

标签: android android-fragments

我已经看到了很多关于片段的问题,我似乎仍然无法弄清楚我想做的事情是否可行,如果我的设计模式只是有缺陷我需要重新完成整个过程。基本上,就像大多数问题一样,我有一个带有NavigationTabs的ActionBar(使用ActionBarSherlock),然后在每个Tab中都有一个FragementActivity,然后FragmentActivities在选择一行时推送新的Fragments(我正在尝试重新创建) Android中的iOS项目,它只是一个基于导航的基本应用程序,其中包含一些可以深入查看特定信息的选项卡。当我单击手机上的后退按钮时,前一个片段已加载,但片段重新创建(因此每个视图再次调用WebServices)并且不需要这样做,因为在以前的视图中信息不会改变倒退。所以基本上我想弄清楚的是如何设置我的片段,这样当我按下手机上的后退按钮时,前面的片段只是拉起来已经创建了之前的项目。以下是我目前的代码:

    //This is from my FragmentActivity Class that contains the ActionBar and Tab Selection Control
    @Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub
    int selectedTab = tab.getPosition();

    if (selectedTab == 0) {
        SalesMainScreen salesScreen = new SalesMainScreen();
        ft.replace(R.id.content, salesScreen);
    }
    else if (selectedTab == 1) {
        ClientMainScreen clientScreen = new ClientMainScreen();
        ft.replace(R.id.content, clientScreen);
    }.....

   //This is within the ClientMainScreen Fragment Class, which handles moving to the Detail Fragment
   row.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            //Do something if Row is clicked
                            try{
                                String selectedClientName = clientObject.getString("ClientName");
                                String selectedClientID = clientObject.getString("ClientID");
                                String selectedValue = clientObject.getString("ClientValue");
                                transaction = getFragmentManager().beginTransaction();
                                ClientDetailScreen detailScreen = new ClientDetailScreen();
                                detailScreen.clientID = selectedClientID;
                                detailScreen.clientName = selectedClientName;
                                detailScreen.clientValue = selectedValue;
                                int currentID = ((ViewGroup)getView().getParent()).getId();
                                transaction.replace(currentID,detailScreen);
                                transaction.addToBackStack(null);
                                transaction.commit();

                            }
                            catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });....

     //And then this is the Client Detail Fragment, with the method being called to Call the Web Service and create thew (since what is displayed on this screen is dependent on what is found in the Web Service
          @Override
public View onCreateView(LayoutInflater inflater, ViewGroup group, Bundle saved) {
    return inflater.inflate(R.layout.clientdetailscreen, group, false);
}

@Override
public void onActivityCreated (Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    //Setup Preferences File Link
    this.preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());

    //initialize the table object
    mainTable = (TableLayout)getActivity().findViewById(R.id.mainTable);

    //setup the detail table
    setupRelatedClientSection();

}

客户端详细信息屏幕可以再次向下钻取,使用与客户端主屏幕相同的方法但是当我从新屏幕返回到详细信息屏幕时,再次调用seuptRelatedClientSection()方法,因此整个片段当我真的想要拉出该屏幕的保存版本时重建。这可能与我目前的设置有关,还是我以错误的方式接近这个?

3 个答案:

答案 0 :(得分:7)

我相信您正在寻找show()hide()

我认为你仍然可以将它们添加到后台。

 transaction.hide(currentFragment);
 transaction.show(detailScreen);
 transaction.addToBackStack(null);
 transaction.commit();

我没有看到我的代码,但我相信这是怎么回事......尝试一下,除非别人有更好的方法。 我没有尝试使用show()hide()的backstack,但我相信它会在事务提交之前进行更改,如果按下后退按钮则会撤消它们。我有兴趣知道这个原因请回复我。

您还必须确保在调用之前创建了详细信息片段。由于它基于someitem的点击,因此您应该在每次单击时创建详细信息片段以确保创建正确的详细信息片段。

答案 1 :(得分:4)

我将此答案发布给将来可能会提及此问题的人。

下面的代码将演示如何从FragmentA打开FragmentB并通过按下后退按钮从FragmentB返回FragmentA(不刷新FragmentA)。

public class FragmentA extends Fragment{

   ...

   void openFragmentB(){

       FragmentManager fragmentManager = 
           getActivity().getSupportFragmentManager();
       FragmentB fragmentB = FragmentB.newInstance();

       if (fragmentB.isAdded()) {

           return;
       } else {

           fragmentManager.
               beginTransaction().
               add(R.id.mainContainer,fragmentB).
               addToBackStack(FragmentB.TAG).
               commit();
      }
   }
}

public class FragmentB extends Fragment{

    public static final String TAG = 
        FragmentB.class.getSimpleName();

    ...

    public static FragmentB newInstance(){

        FragmentB fragmentB = new FragmentB();
        return fragmentB;
    }

    @Override
    public void onResume() {

        super.onResume();
        // add this piece of code in onResume method
        this.getView().setFocusableInTouchMode(true);
        this.getView().requestFocus();
    }
}

在MainActivity中覆盖onBackPressed()

class MainActivity extends Activity{
    ...

    @Override
    public void onBackPressed() {

        if (getFragmentManager().getBackStackEntryCount() > 0) {

            getFragmentManager().popBackStack();
        } else {

            super.onBackPressed();
        }
    } 
}

答案 2 :(得分:0)

你说得对,以前有很多关于这个主题的问题/文件;)

有关碎片的文档,特别是有关交易和保存状态的部分,将指导您找到答案。

http://developer.android.com/guide/components/fragments.html#Transactions

http://developer.android.com/guide/components/activities.html#SavingActivityState

Android - Fragment onActivityResult avoid reloading

片段可以支持onSaveInstanceState但不支持onRestoreInstanceState,因此如果您想保存对表格视图的引用,请将它们保存到Bundle,然后您就可以访问已保存的视图在您的onActivityCreated方法中。你也可以使用Fragments back stack。

This guide/tutorial在后栈和保留片段状态上有非常详细的说明/示例。

祝你好运