onCreate方法在方向更改时调用两次

时间:2014-06-27 09:07:44

标签: android android-fragments

为什么在OrientListFragment中的onCreate方法在方向更改时调用了两次?首次调用应用程序崩溃后,getActivity()内的onPostExecute会返回null,因此我尝试更改:

new HttpTask(this).execute("");

if(savedInstanceStata == null)
     new HttpTask(this).execute("");

然后在第二次调用时,savedInstanceState为null,因此mActivatedPosition始终为ListView.INVALID_POSITION。 我正在使用布局别名,因此activity_list被activity_twopane替换。

MainActivity

public class MainActivity extends Activity implements
    TabListener, OnNavigationListener {

/**
 * Whether or not the activity is in two-pane mode, i.e. running on a tablet
 * device.
 */
private boolean mTwoPane = false;
ResourceReservationApp app = (ResourceReservationApp)getApplication();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list);
    mTwoPane = getResources().getBoolean(R.bool.has_two_panes);

    if(mTwoPane){
     // Set up the action bar to show tabs.
    final ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    final String[] dropdownValues = getResources().getStringArray(R.array.dropdown);
    for (String item : dropdownValues) 
        actionBar.addTab(actionBar.newTab().setText(item).setTabListener(this));    

    }else{
        ActionBar actionBar = getActionBar();
         actionBar.setDisplayShowTitleEnabled(false);
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

            final String[] dropdownValues = getResources().getStringArray(R.array.dropdown);

            ArrayAdapter<String> adapter = new ArrayAdapter<String>(actionBar.getThemedContext(),
                android.R.layout.simple_spinner_item, android.R.id.text1,
                dropdownValues);

            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            actionBar.setListNavigationCallbacks(adapter, this);                            
    }


}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.activity_item_list, menu);
    return super.onCreateOptionsMenu(menu);
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {

    if(tab.getText().equals("Resources")){
         ResourceListFragment fragment = new ResourceListFragment();            
                getFragmentManager().beginTransaction()
                .replace(R.id.fragment_list, fragment).commit();             
    }
    if(tab.getText().equals("Reservations")){
         ReservationListFragment fragment = new ReservationListFragment();                          
                getFragmentManager().beginTransaction()
                .replace(R.id.fragment_list, fragment).commit();                    
    }
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
    // TODO Auto-generated method stub

}
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
     final String[] dropdownValues = getResources().getStringArray(R.array.dropdown);
     if(dropdownValues[itemPosition].equals("Resources")){
         ResourceListFragment fragment = new ResourceListFragment();
            getFragmentManager().beginTransaction()
                    .replace(R.id.activity_list, fragment).commit();
     }
     if(dropdownValues[itemPosition].equals("Reservations")){
         ReservationListFragment fragment = new ReservationListFragment();                                  
            getFragmentManager().beginTransaction()
                    .replace(R.id.activity_list, fragment).commit();
     }
    return true;
}
    }

activity_list.xml

 <?xml version="1.0" encoding="utf-8"?>
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     />

ResourceListFragment

public class ResourceListFragment extends ListFragment {
private boolean mTwoPane =false;
/**
 * The serialization (saved instance state) Bundle key representing the
 * activated item position. Only used on tablets.
 */
private static final String STATE_ACTIVATED_POSITION = "activated_position";
/**
 * The current activated item position. Only used on tablets.
 */
private int mActivatedPosition = ListView.INVALID_POSITION;

public ResourceListFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);         
    mTwoPane = getResources().getBoolean(R.bool.has_two_panes);
    new HttpTask(this).execute("");
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if(mTwoPane){
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        if (savedInstanceState != null
                && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
            setActivatedPosition(savedInstanceState
                    .getInt(STATE_ACTIVATED_POSITION));
        }
    }       
}


@Override
public void onListItemClick(ListView listView, View view, int position,
        long id) {
    super.onListItemClick(listView, view, position, id);

    // Notify the active callbacks interface (the activity, if the
    // fragment is attached to one) that an item has been selected.

    ((ResourceReservationApp)getActivity().getApplication()).setSelectedResource((Resource)(listView.getAdapter().getItem(position)));  
    if (mTwoPane) {
        // In two-pane mode, show the detail view in this activity by
        // adding or replacing the detail fragment using a
        // fragment transaction.

        setActivatedPosition(position);

        Bundle arguments = new Bundle();
        arguments.putString(ResourceDetailFragment.ARG_ITEM_ID, id+"");
        ResourceDetailFragment fragment = new ResourceDetailFragment();
        fragment.setArguments(arguments);
        getActivity().getFragmentManager().beginTransaction()
                .replace(R.id.detail_container, fragment).commit();

    } else {

        // In single-pane mode, simply start the detail activity
        // for the selected item ID.
        Intent detailIntent = new Intent(getActivity(), ResourceDetailActivity.class);
        detailIntent.putExtra(ResourceDetailFragment.ARG_ITEM_ID, id);          
        startActivity(detailIntent);
    }

}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if(mTwoPane) {
        // Serialize and persist the activated item position.
        outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
        outState.putParcelable("AS",(Parcelable) getActivity());
    }
}

/**
 * Turns on activate-on-click mode. When this mode is on, list items will be
 * given the 'activated' state when touched.
 */


private void setActivatedPosition(int position) {
    if(mTwoPane)
    if (position == ListView.INVALID_POSITION) {
        getListView().setItemChecked(mActivatedPosition, false);
    } else {
        getListView().setItemChecked(position, true);
    }       
    mActivatedPosition = position;
}
 private class HttpTask extends AsyncTask<String, Void, List<Resource>> {
        String message="Received";
        ResourceListFragment fragment;
        ProgressDialog dialog;


        public HttpTask(ResourceListFragment fragment){
            this.fragment=fragment;

        }


        @Override
        protected void onPreExecute() {
             dialog = ProgressDialog.show(getActivity(), "Loading...", "Please wait...", true);
        }



        @Override
        protected List<Resource> doInBackground(String... credentials) {
            List<Resource>resources=null;
            try {
                resources =ResourceDAO.getResourcesFromService("gataric","gataric");
                if(resources== null){
                    message  = "Error occured!";
                    return resources;
                }                   
            } catch (HttpException e) { 
                message = e.getMessage();

            }
            return resources;
        }      
        @Override
        protected void onPostExecute(List<Resource> result) {
            dialog.dismiss();               
            if(result!=null)
            fragment.setListAdapter(new ArrayAdapter<Resource>(getActivity(),
                    android.R.layout.simple_list_item_activated_1,
                    android.R.id.text1, result));
            fragment.setActivatedPosition(fragment.mActivatedPosition);
            //Toast.makeText(getActivity().getBaseContext(), message, Toast.LENGTH_LONG).show();
       }
    }
        }

activity_twopane.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle"
tools:context="com.example.resourcereservation.ResourceListActivity" >

<FrameLayout
    android:id="@+id/fragment_list"        
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    />

<FrameLayout
    android:id="@+id/detail_container"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="3" />

2 个答案:

答案 0 :(得分:1)

当您的方向更改活动被销毁并重新创建但在重新创建之前onSaveInstanceState()被调用。因此,请使用onSaveInstanceState()方法保存数据。然后,您可以在onCreate()onRestoreInstanceState()期间恢复状态。 见this

答案 1 :(得分:0)

您原来的问题:

为什么在OrientListFragment中的onCreate方法在方向更改时调用了两次?

是的,我偶尔也见过这个,并想知道为什么。请参阅Ted Hopp的答案(不是公认的答案):

onCreate(...) is called twice after the device is rotated

你的问题:

禁用方向更改不被视为良好做法:

How do I disable orientation change on Android?

我确定你意识到,在inPostExecute中你需要这样的东西

if (getActivity() != null){
    ...
}