14

I've seen quite a few questions on SO about Fragments and I still can't seem to figure out if what I want to do is possible, and more so if my design pattern is just flawed and I need to re-work the entire process. Basically, like most questions that have been asked, I have an ActionBar with NavigationTabs (using ActionBarSherlock), then within each Tab there is a FragementActivity and then the FragmentActivities push new Fragments when a row is selected (I'm trying to re-create an iOS Project in Android and it's just a basic Navigation based app with some tabs that can drill down into specific information). When I click the back button on the phone the previous Fragment is loaded but the Fragment re-creates itself (so the WebServices are called again for each view) and this isn't needed since the information won't change in a previous view when going backwards. So basically what I want to figure out is how do I setup my Fragments so that when I push the back button on the phone, the previous Fragment is just pulled up with the previous items already created. Below is my current code :

    //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();

}

The Client Detail Screen can then drill down one more time, using the same method as the Client Main Screen but when I go back from that new screen to the Detail Screen the seuptRelatedClientSection() method is called again and so the entire Fragment is rebuilt when really I just want to pull up a saved version of that screen. Is this possible with my current setup, or did I approach this the wrong way?

4

4 回答 4

13

尝试使用 fagementTransaction.add 而不是替换

于 2015-08-25T10:38:28.990 回答
7

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

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

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

我没有要查看的代码,但我相信这就是它的运行方式...尝试一下,除非其他人有更好的方法。我没有尝试过使用 show() hide() 的 backstack,但我相信它会接受在事务提交之前所做的更改,并且如果按下后退按钮将撤消它们。请就这个问题与我联系,因为我很想知道。

您还必须确保在调用它之前创建了详细信息片段。由于它是基于对某个项目的单击,因此您可能应该在每次单击时创建详细信息片段,以确保创建了正确的详细信息片段。

于 2012-12-12T23:46:24.000 回答
5

我将这个答案发布给将来可能会提到这个问题的人。

以下代码将演示如何通过按返回按钮从 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();
        }
    } 
}
于 2017-05-19T04:35:29.390 回答
0

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

有关 Fragments 的文档,特别是有关事务和保存状态的部分,将引导您找到答案。

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

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

Android - 片段 onActivityResult 避免重新加载

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

本指南/教程在回栈和保留片段状态上有非常详细的说明/示例。

祝你好运

于 2012-12-12T23:52:42.640 回答