Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在方向更改时创建两次片段_Android_Android Fragments_Android Activity_Android Recyclerview_Android Lifecycle - Fatal编程技术网

Android 在方向更改时创建两次片段

Android 在方向更改时创建两次片段,android,android-fragments,android-activity,android-recyclerview,android-lifecycle,Android,Android Fragments,Android Activity,Android Recyclerview,Android Lifecycle,我有一个MainListActivity,它显示一个ListFragment,它使用RecyclerView来显示项目的网格。使用ListFragment的onAttach中的SyncAdapter从REST-API获取项目。使用片段的savedInstanceState上的,我正在保存recyclerviews当前的滚动位置,并在重新创建视图时检索它。在MainListActivity中,我仅在savedinstantstate为空时创建一个新片段 按照生命周期,每次我旋转屏幕时,片段都会被重

我有一个
MainListActivity
,它显示一个
ListFragment
,它使用
RecyclerView
来显示项目的网格。使用
ListFragment
onAttach
中的
SyncAdapter
从REST-API获取项目。使用片段的savedInstanceState上的
,我正在保存recyclerviews当前的滚动位置,并在重新创建视图时检索它。在
MainListActivity
中,我仅在
savedinstantstate
为空时创建一个新片段

按照生命周期,每次我旋转屏幕时,片段都会被重新创建。但我使用日志观察到,片段被重新创建了两次,并且我失去了先前保存的on状态

主列表活动:

public class MainListActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {

        ....
        ....

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setupWindowAnimations();
            ButterKnife.bind(this);
            setContentView(R.layout.activity_main_list);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            getSupportActionBar().setDisplayShowTitleEnabled(false);
            toolbar.setTitle(R.string.state_prompt);

            if(savedInstanceState == null) {
                Log.e(TAG, "onCreate: HERE 1");
                listFragment = (ListFragment) getSupportFragmentManager().findFragmentById(R.id.list_container);
                if (listFragment == null) {
                    Log.e(TAG, "onCreate: HERE 1");
                    listFragment = ListFragment.newInstance(this, state);
                    getSupportFragmentManager().beginTransaction()
                            .add(R.id.list_container, listFragment)
                            .commit();
                }
            }

        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main_list, menu);
            MenuItem item = menu.findItem(R.id.spinner);
            spinner = (Spinner) MenuItemCompat.getActionView(item);
            item.setTitle(getResources().getString(R.string.state_prompt));
            spinner.setDropDownWidth(130);
            spinner.setPopupBackgroundResource(R.color.primaryText);
            ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
                    R.array.state_arrays, R.layout.spinner_item);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinner.setAdapter(adapter);
            spinner.setOnItemSelectedListener(this);
            return true;
        }

        @Override
        public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long l) {
            state = String.valueOf(spinner.getSelectedItem());
            listFragment = ListFragment.newInstance(this, state);
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.list_container, listFragment)
                    .commit();
         }


        @Override
        protected void onSaveInstanceState(Bundle outState) {
            outState.putString(SELECTED_STATE, state);
            super.onSaveInstanceState(outState);
        }

}
在片段的onCreate方法中使用setRetainInstance(true)

公共void setRetainInstance(布尔保留)

控制是否在活动重新创建期间保留片段实例(例如从配置更改)。这只能用于不在后堆栈中的片段。如果设置,则重新创建活动时片段生命周期将略有不同:

  • 不会调用onDestroy()(但仍然会调用onDetach(),因为 正在从当前活动中分离片段)
  • 由于未重新创建片段,因此不会调用onCreate(Bundle)
  • 仍将调用onAttach(活动)和onActivityCreated(捆绑)

可以考虑使用VIEW模型。它是为了解决这个问题而创建的。
public class ListFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{

    static int currentVisiblePosition = 0;

    public ListFragment() {
    }

    public static ListFragment newInstance(Context context, String state) {
        Bundle arguments = new Bundle();
        ListFragment fragment = new ListFragment();
        arguments.putString(SELECTED_STATE, state);
        fragment.setArguments(arguments);
        return fragment;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        ParkSyncAdapter.performSync(state, max_article);
        MobileAds.initialize(getActivity(), "ca-app-pub-1510923228147176~5607247189");
        Log.e(TAG, "onAttach: HERE");
    }


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            currentVisiblePosition = savedInstanceState.getInt(LIST_STATE_KEY);
        }
        getLoaderManager().initLoader(LOADER_ID, null, this);

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list_fragment, container, false);
        mAdView = new AdView(getActivity());
        mAdView.setAdUnitId("ca-app-pub-1510923228147176/1177047580");
        mAdView.setAdSize(AdSize.BANNER);
        LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.admob_ll);
        linearLayout.addView(mAdView);
        AdRequest adRequest = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).addTestDevice("Somestring").build();
        mAdView.loadAd(adRequest);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        ButterKnife.bind(this, view);
        adapter = new ListAdapter(this, getContext());
        if (idlingResource != null) {
            idlingResource.setIdleState(true);
        }
        progressBar.setVisibility(View.VISIBLE);
        recyclerView.setAdapter(adapter);
        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            layoutManager = new GridLayoutManager(getActivity(), 2);
            recyclerView.setLayoutManager(layoutManager);
        } else {
            layoutManager = new GridLayoutManager(getActivity(), 4);
            recyclerView.setLayoutManager(layoutManager);
        }
        Log.e(TAG, "onViewCreated: POSITION: "+currentVisiblePosition);
        recyclerView.getLayoutManager().scrollToPosition(currentVisiblePosition);
        currentVisiblePosition = 0;
        View detailsView = getActivity().findViewById(R.id.details);
        mDualPane = detailsView != null && detailsView.getVisibility() == View.VISIBLE;

    }



    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        currentVisiblePosition = ((GridLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
        Log.e(TAG, "onSaveInstanceState: POSITION: "+currentVisiblePosition);
        outState.putInt(LIST_STATE_KEY, currentVisiblePosition);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy: HERE");
        super.onDestroy();
    }

    @NonNull
    @Override
    public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
        uri = ParkContract.ParkEntry.CONTENT_URI_PARKS;
        return new CursorLoader(getActivity(), uri, PROJECTION, null, null, null);
    }

    @Override
    public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
        adapter.swapCursor(data);
        recyclerView.setVisibility(View.VISIBLE);
        progressBar.setVisibility(View.INVISIBLE);
    }

    @Override
    public void onLoaderReset(@NonNull Loader<Cursor> loader) {
        if (adapter != null) {
            adapter.swapCursor(null);
        }
    }
}
// ****Fragment created for the 1st time
    07-23 19:03:15.674 E/ListFragment: onAttach: HERE                    
    07-23 19:03:15.898 E/ListFragment: onViewCreated: POSITION: 0
// ****Not sure why Fragment gets recreated here 2nd time
    07-23 19:03:17.292 E/ListFragment: onAttach: HERE
    07-23 19:03:17.321 E/ListFragment: onDestroy: HERE
    07-23 19:03:17.403 E/ListFragment: onViewCreated: POSITION: 0
// ****Orientation change, saving RecyclerView's position
    07-23 19:03:33.557 E/ListFragment: onSaveInstanceState: POSITION: 6
    07-23 19:03:33.612 E/ListFragment: onDestroy: HERE
    07-23 19:03:33.677 E/ListFragment: onAttach: HERE
    07-23 19:03:33.805 E/stetho: Could not start Stetho server: main
// ****Position correctly retrieved
    07-23 19:03:33.859 E/ListFragment: onViewCreated: POSITION: 6
// ****Again,  Fragment gets recreated here 2nd time loosing the previously saved position
    07-23 19:03:34.394 E/ListFragment: onAttach: HERE
    07-23 19:03:34.406 E/ListFragment: onDestroy: HERE
    07-23 19:03:34.471 E/ListFragment: onViewCreated: POSITION: 0