onLoadReset 后 savedInstanceState 为空,但如果调用 onCreate 而 onLoadReset 未调用(如设备旋转时),则效果很好
savedInstanceState empty after onLoadReset but works well if onCreate is called and onLoadReset is not(like in case of device rotation)
我有一个片段,我在其中使用 AsyncTaskLoader 从 API 获取数据,然后分别使用自定义适配器膨胀两个单独的 RecyclerView。问题是,当我单击回收器视图进入该特定位置的详细信息 Activity,然后返回到原始 Activity,我发现 saveInstanceState 是空的。但如果我确实旋转我的设备,它会工作得很好。我认为这不是正确的行为。如果它适用于屏幕旋转,那么它也应该适用于我遇到的问题。
这是我的片段的代码:
public class MoviePosterFragment extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<Movie>> {
private static final int POPULAR_MOVIE_LOADER_ID = 1111;
private static final int UPCOMING_MOVIE_LOADER_ID = 9999;
ArrayList<Movie> popularMovies;
ArrayList<Movie> upcomingMovies;
PopularMoviesAdapter mPopularMoviesAdapter;
UpcomingMovieAdapter mUpcomingMovieAdapter;
RecyclerView mPopularMovieRecyclerView;
RecyclerView mUpcomingMovieRecyclerView;
Uri.Builder uriBuilder;
String savedInstance;
LinearLayoutManager layoutManagerPopularMoviesPoster;
LinearLayoutManager layoutManagerUpcomingMoviesPoster;
public MoviePosterFragment() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("############******", "onCreate called");
if (savedInstanceState == null) {
popularMovies = new ArrayList<>();
upcomingMovies = new ArrayList<>();
savedInstance = "empty";
Log.v("############******", "onCreate savedInstance is " + savedInstance);
//First of all check if network is connected or not then only start the loader
ConnectivityManager connMgr = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
/*
*fetch data. Get a reference to the LoaderManager, in order to interact with loaders.
*/
Log.v("############******", "startPopularMoviesLoaderManager called");
startPopularMoviesLoaderManager();
Log.v("############******", "startUpcomingMoviesLoaderManager called");
startUpcomingMoviesLoaderManager();
}
} else {
savedInstance = "not empty";
Log.v("############******", "onCreate savedInstance is " + savedInstance);
popularMovies = savedInstanceState.getParcelableArrayList("popularMovies");
upcomingMovies = savedInstanceState.getParcelableArrayList("upcomingMovies");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.v("############******", "onCreateView savedInstance is " + savedInstanceState);
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_movie_posters, container, false);
/* Code referenced from the @link:
* "https://guides.codepath.com/android/using-the-recyclerview"
*/
/*
* Lookup the recyclerView in activity layout
*/
mPopularMovieRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerViewPopularMovies);
mUpcomingMovieRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerViewTopMoviesMovies);
/*
* Setup layout manager for items with orientation
* Also supports `LinearLayoutManager.HORIZONTAL`
*/
layoutManagerPopularMoviesPoster = new LinearLayoutManager(getActivity(),
LinearLayoutManager.HORIZONTAL, false);
/* Optionally customize the position you want to default scroll to */
layoutManagerPopularMoviesPoster.scrollToPosition(0);
/* Attach layout manager to the RecyclerView */
mPopularMovieRecyclerView.setLayoutManager(layoutManagerPopularMoviesPoster);
/*
* Setup layout manager for items with orientation
* Also supports `LinearLayoutManager.HORIZONTAL`
*/
layoutManagerUpcomingMoviesPoster = new LinearLayoutManager(getActivity(),
LinearLayoutManager.HORIZONTAL, false);
/* Optionally customize the position you want to default scroll to */
layoutManagerUpcomingMoviesPoster.scrollToPosition(0);
/* Attach layout manager to the RecyclerView */
mUpcomingMovieRecyclerView.setLayoutManager(layoutManagerUpcomingMoviesPoster);
SnapHelper snapHelperForPopularMovieRecyclerView = new GravitySnapHelper(Gravity.START);
snapHelperForPopularMovieRecyclerView.attachToRecyclerView(mPopularMovieRecyclerView);
SnapHelper snapHelperForUpcomingMovieRecyclerView = new GravitySnapHelper(Gravity.START);
snapHelperForUpcomingMovieRecyclerView.attachToRecyclerView(mUpcomingMovieRecyclerView);
/* Code referenced from the @link:
* "https://guides.codepath.com/android/using-the-recyclerview"
*/
// Create mPopularMoviesAdapter passing in the sample user data
mPopularMoviesAdapter = new PopularMoviesAdapter(getActivity(), popularMovies);
mPopularMoviesAdapter.setMovieData(popularMovies);
// Attach the mPopularMoviesAdapter to the recyclerview to populate items
mPopularMovieRecyclerView.setAdapter(mPopularMoviesAdapter);
// Create mUpcomingMoviesAdapter passing in the sample user data
mUpcomingMovieAdapter = new UpcomingMovieAdapter(getActivity(), upcomingMovies);
mUpcomingMovieAdapter.setMovieData(upcomingMovies);
// Attach the mUpcomingMoviesAdapter to the recyclerview to populate items
mUpcomingMovieRecyclerView.setAdapter(mUpcomingMovieAdapter);
return rootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.v("############******", "onActivityCreated called and saveInstance is " + savedInstanceState);
mPopularMoviesAdapter = new PopularMoviesAdapter(getActivity(), popularMovies);
mUpcomingMovieAdapter = new UpcomingMovieAdapter(getActivity(), upcomingMovies);
mUpcomingMovieAdapter.setMovieData(upcomingMovies);
mPopularMoviesAdapter.setMovieData(popularMovies);
mPopularMovieRecyclerView.setAdapter(mPopularMoviesAdapter);
mUpcomingMovieRecyclerView.setAdapter(mUpcomingMovieAdapter);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.v("############******", "onSaveInstanceState called");
outState.putParcelableArrayList("popularMovies", popularMovies);
outState.putParcelableArrayList("upcomingMovies", upcomingMovies);
}
private void startPopularMoviesLoaderManager() {
LoaderManager loaderManager = getLoaderManager();
Log.v("############******", "initLoader called with id " + POPULAR_MOVIE_LOADER_ID);
loaderManager.initLoader(POPULAR_MOVIE_LOADER_ID, null, this);
Log.v("############******", "startPopularMoviesLoaderManager finished");
}
private void startUpcomingMoviesLoaderManager() {
LoaderManager loaderManager = getLoaderManager();
Log.v("############******", "initLoader called with id " + UPCOMING_MOVIE_LOADER_ID);
loaderManager.initLoader(UPCOMING_MOVIE_LOADER_ID, null, this);
Log.v("############******", "startUpcomingMoviesLoaderManager finished");
}
@Override
public Loader<ArrayList<Movie>> onCreateLoader(int id, Bundle args) {
if (id == POPULAR_MOVIE_LOADER_ID) {
Log.v("############******", "onCreateLoader called with id " + POPULAR_MOVIE_LOADER_ID);
Uri baseUri = Uri.parse(UrlsAndConstants.MoviePosterQuery.DEFAULT_URL);
Log.v("############", "baseUri is " + baseUri.toString());
uriBuilder = baseUri.buildUpon();
Log.v("############", "uriBuilder is " + uriBuilder.toString());
uriBuilder.appendQueryParameter(API_KEY_PARAM, API_KEY_PARAM_VALUE);
Log.v("############", "uriBuilder.toString() is " + uriBuilder.toString());
uriBuilder.appendQueryParameter(SORT_BY_KEY, SORT_BY_POPULARITY_VALUE_DESCENDING);
} else if (id == UPCOMING_MOVIE_LOADER_ID) {
Log.v("############", "onCreateLoader called with id " + UPCOMING_MOVIE_LOADER_ID);
Uri baseUri = Uri.parse("https://api.themoviedb.org/3/movie/upcoming");
Log.v("############", "baseUri is " + baseUri.toString());
uriBuilder = baseUri.buildUpon();
Log.v("############", "uriBuilder is " + uriBuilder.toString());
uriBuilder.appendQueryParameter(API_KEY_PARAM, API_KEY_PARAM_VALUE);
Log.v("############", "uriBuilder.toString() is " + uriBuilder.toString());
}
return new MoviePosterLoader(getActivity().getApplicationContext(), uriBuilder.toString());
}
@Override
public void onLoadFinished(Loader<ArrayList<Movie>> loader, ArrayList<Movie> incomingMovieArrayList) {
switch (loader.getId()) {
case POPULAR_MOVIE_LOADER_ID:
Log.v("############******", "onLoadFinished called with id " + POPULAR_MOVIE_LOADER_ID);
if (incomingMovieArrayList.isEmpty()) {
Log.v("******************", "popularMovies isEmpty");
return;
} else {
popularMovies = incomingMovieArrayList;
mPopularMoviesAdapter = new PopularMoviesAdapter(getActivity(), popularMovies);
mPopularMoviesAdapter.setMovieData(popularMovies);
mPopularMovieRecyclerView.setAdapter(mPopularMoviesAdapter);
}
break;
case UPCOMING_MOVIE_LOADER_ID:
Log.v("############******", "onLoadFinished called with id " + UPCOMING_MOVIE_LOADER_ID);
if (incomingMovieArrayList.isEmpty()) {
Log.v("******************", "popularMovies isEmpty");
return;
} else {
upcomingMovies = incomingMovieArrayList;
mUpcomingMovieAdapter = new UpcomingMovieAdapter(getActivity(), upcomingMovies);
mUpcomingMovieAdapter.setMovieData(upcomingMovies);
mUpcomingMovieRecyclerView.setAdapter(mUpcomingMovieAdapter);
}
break;
}
}
@Override
public void onLoaderReset(Loader<ArrayList<Movie>> loader) {
Log.v("############******", "onLoaderReset called ");
}
}
和 正如您在下面的 Logcat 消息中看到的,问题肯定在那里。
Logcat 消息:
`首次启动应用程序时:
12-07 01:37:56.450 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:37:56.450 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is empty
12-07 01:37:56.450 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager called
12-07 01:37:56.453 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 1111
12-07 01:37:56.453 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateLoader called with id 1111
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager finished
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager called
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 9999
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager finished
12-07 01:37:56.456 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is null
12-07 01:37:56.493 9756-9756/me.abhishekraj.showmyshow V/############******: onActivityCreated called and saveInstance is null
12-07 01:37:57.683 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 9999
12-07 01:37:57.731 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 1111
After a popular movie poster is clicked
12-07 01:29:16.062 2256-2256/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
After coming back from DetailActivity
12-07 01:38:52.785 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:38:52.785 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is empty
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 1111
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateLoader called with id 1111
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager finished
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 9999
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager finished
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is null
12-07 01:38:52.855 9756-9756/me.abhishekraj.showmyshow V/############******: onActivityCreated called and saveInstance is null
12-07 01:38:53.326 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 9999
12-07 01:38:54.033 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 1111
After a upcoming movie poster is clicked
12-07 01:30:04.572 2256-2256/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
After coming back from DetailActivity
12-07 01:39:51.672 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:39:51.672 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is empty
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager called
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 1111
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateLoader called with id 1111
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager finished
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager called
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 9999
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager finished
12-07 01:39:51.761 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is null
12-07 01:39:51.765 9756-9756/me.abhishekraj.showmyshow V/############******: onActivityCreated called and saveInstance is null
12-07 01:39:51.815 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 1111
12-07 01:39:51.817 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 9999
on rotate
12-07 01:40:18.441 9756-9756/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
12-07 01:40:18.472 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:40:18.472 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is not empty
12-07 01:40:18.478 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is Bundle[{upcomingMovies=[me.abhishekraj.showmyshow.Movie@c837a9f, me.abhishekraj.showmyshow.Movie@42b07b5, me.abhishekraj.showmyshow.Movie@da99e4a,.......and so on..that means it's not empty
onRotating back
12-07 01:40:48.244 9756-9756/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
12-07 01:40:48.281 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:40:48.281 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is not empty
12-07 01:40:48.286 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is Bundle[{upcomingMovies=[me.abhishekraj.showmyshow.Movie@c837a9f, me.abhishekraj.showmyshow.Movie@42b07b5, me.abhishekraj.showmyshow.Movie@da99e4a, me.abhishekraj.showmyshow.Movie@67a86d8, me.abhishekraj.showmyshow.Movie@a516a31, me.abhishekraj.showmyshow.Movie@e241e97,.....and so on...that means it's not empty`
那问题出在哪里呢?为什么当我 return 从另一个 activity 到这个片段时我得到空白的 saveInstanceState 而不是空的 saveInstanceState 用于屏幕旋转,即使在这两种情况下再次创建 activity 也是如此(???) .
谢谢!
编辑:
如果需要更多我的代码来引用,那么可以在下面找到:Gist
如果将 main activity 的启动模式用作单顶,这个问题可以很容易地处理,这在我的用例中似乎完全可以接受。这是解决问题后我的 manifest.xml 的样子:
<activity
android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
但是,更好的方法是使用 Back Stack,这样 activity 状态可以在被销毁之前保存下来。当我使用 back-stack 解决它时,我会更新答案,但现在它完成了工作。
我有一个片段,我在其中使用 AsyncTaskLoader 从 API 获取数据,然后分别使用自定义适配器膨胀两个单独的 RecyclerView。问题是,当我单击回收器视图进入该特定位置的详细信息 Activity,然后返回到原始 Activity,我发现 saveInstanceState 是空的。但如果我确实旋转我的设备,它会工作得很好。我认为这不是正确的行为。如果它适用于屏幕旋转,那么它也应该适用于我遇到的问题。
这是我的片段的代码:
public class MoviePosterFragment extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<Movie>> {
private static final int POPULAR_MOVIE_LOADER_ID = 1111;
private static final int UPCOMING_MOVIE_LOADER_ID = 9999;
ArrayList<Movie> popularMovies;
ArrayList<Movie> upcomingMovies;
PopularMoviesAdapter mPopularMoviesAdapter;
UpcomingMovieAdapter mUpcomingMovieAdapter;
RecyclerView mPopularMovieRecyclerView;
RecyclerView mUpcomingMovieRecyclerView;
Uri.Builder uriBuilder;
String savedInstance;
LinearLayoutManager layoutManagerPopularMoviesPoster;
LinearLayoutManager layoutManagerUpcomingMoviesPoster;
public MoviePosterFragment() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("############******", "onCreate called");
if (savedInstanceState == null) {
popularMovies = new ArrayList<>();
upcomingMovies = new ArrayList<>();
savedInstance = "empty";
Log.v("############******", "onCreate savedInstance is " + savedInstance);
//First of all check if network is connected or not then only start the loader
ConnectivityManager connMgr = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
/*
*fetch data. Get a reference to the LoaderManager, in order to interact with loaders.
*/
Log.v("############******", "startPopularMoviesLoaderManager called");
startPopularMoviesLoaderManager();
Log.v("############******", "startUpcomingMoviesLoaderManager called");
startUpcomingMoviesLoaderManager();
}
} else {
savedInstance = "not empty";
Log.v("############******", "onCreate savedInstance is " + savedInstance);
popularMovies = savedInstanceState.getParcelableArrayList("popularMovies");
upcomingMovies = savedInstanceState.getParcelableArrayList("upcomingMovies");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.v("############******", "onCreateView savedInstance is " + savedInstanceState);
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_movie_posters, container, false);
/* Code referenced from the @link:
* "https://guides.codepath.com/android/using-the-recyclerview"
*/
/*
* Lookup the recyclerView in activity layout
*/
mPopularMovieRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerViewPopularMovies);
mUpcomingMovieRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerViewTopMoviesMovies);
/*
* Setup layout manager for items with orientation
* Also supports `LinearLayoutManager.HORIZONTAL`
*/
layoutManagerPopularMoviesPoster = new LinearLayoutManager(getActivity(),
LinearLayoutManager.HORIZONTAL, false);
/* Optionally customize the position you want to default scroll to */
layoutManagerPopularMoviesPoster.scrollToPosition(0);
/* Attach layout manager to the RecyclerView */
mPopularMovieRecyclerView.setLayoutManager(layoutManagerPopularMoviesPoster);
/*
* Setup layout manager for items with orientation
* Also supports `LinearLayoutManager.HORIZONTAL`
*/
layoutManagerUpcomingMoviesPoster = new LinearLayoutManager(getActivity(),
LinearLayoutManager.HORIZONTAL, false);
/* Optionally customize the position you want to default scroll to */
layoutManagerUpcomingMoviesPoster.scrollToPosition(0);
/* Attach layout manager to the RecyclerView */
mUpcomingMovieRecyclerView.setLayoutManager(layoutManagerUpcomingMoviesPoster);
SnapHelper snapHelperForPopularMovieRecyclerView = new GravitySnapHelper(Gravity.START);
snapHelperForPopularMovieRecyclerView.attachToRecyclerView(mPopularMovieRecyclerView);
SnapHelper snapHelperForUpcomingMovieRecyclerView = new GravitySnapHelper(Gravity.START);
snapHelperForUpcomingMovieRecyclerView.attachToRecyclerView(mUpcomingMovieRecyclerView);
/* Code referenced from the @link:
* "https://guides.codepath.com/android/using-the-recyclerview"
*/
// Create mPopularMoviesAdapter passing in the sample user data
mPopularMoviesAdapter = new PopularMoviesAdapter(getActivity(), popularMovies);
mPopularMoviesAdapter.setMovieData(popularMovies);
// Attach the mPopularMoviesAdapter to the recyclerview to populate items
mPopularMovieRecyclerView.setAdapter(mPopularMoviesAdapter);
// Create mUpcomingMoviesAdapter passing in the sample user data
mUpcomingMovieAdapter = new UpcomingMovieAdapter(getActivity(), upcomingMovies);
mUpcomingMovieAdapter.setMovieData(upcomingMovies);
// Attach the mUpcomingMoviesAdapter to the recyclerview to populate items
mUpcomingMovieRecyclerView.setAdapter(mUpcomingMovieAdapter);
return rootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.v("############******", "onActivityCreated called and saveInstance is " + savedInstanceState);
mPopularMoviesAdapter = new PopularMoviesAdapter(getActivity(), popularMovies);
mUpcomingMovieAdapter = new UpcomingMovieAdapter(getActivity(), upcomingMovies);
mUpcomingMovieAdapter.setMovieData(upcomingMovies);
mPopularMoviesAdapter.setMovieData(popularMovies);
mPopularMovieRecyclerView.setAdapter(mPopularMoviesAdapter);
mUpcomingMovieRecyclerView.setAdapter(mUpcomingMovieAdapter);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.v("############******", "onSaveInstanceState called");
outState.putParcelableArrayList("popularMovies", popularMovies);
outState.putParcelableArrayList("upcomingMovies", upcomingMovies);
}
private void startPopularMoviesLoaderManager() {
LoaderManager loaderManager = getLoaderManager();
Log.v("############******", "initLoader called with id " + POPULAR_MOVIE_LOADER_ID);
loaderManager.initLoader(POPULAR_MOVIE_LOADER_ID, null, this);
Log.v("############******", "startPopularMoviesLoaderManager finished");
}
private void startUpcomingMoviesLoaderManager() {
LoaderManager loaderManager = getLoaderManager();
Log.v("############******", "initLoader called with id " + UPCOMING_MOVIE_LOADER_ID);
loaderManager.initLoader(UPCOMING_MOVIE_LOADER_ID, null, this);
Log.v("############******", "startUpcomingMoviesLoaderManager finished");
}
@Override
public Loader<ArrayList<Movie>> onCreateLoader(int id, Bundle args) {
if (id == POPULAR_MOVIE_LOADER_ID) {
Log.v("############******", "onCreateLoader called with id " + POPULAR_MOVIE_LOADER_ID);
Uri baseUri = Uri.parse(UrlsAndConstants.MoviePosterQuery.DEFAULT_URL);
Log.v("############", "baseUri is " + baseUri.toString());
uriBuilder = baseUri.buildUpon();
Log.v("############", "uriBuilder is " + uriBuilder.toString());
uriBuilder.appendQueryParameter(API_KEY_PARAM, API_KEY_PARAM_VALUE);
Log.v("############", "uriBuilder.toString() is " + uriBuilder.toString());
uriBuilder.appendQueryParameter(SORT_BY_KEY, SORT_BY_POPULARITY_VALUE_DESCENDING);
} else if (id == UPCOMING_MOVIE_LOADER_ID) {
Log.v("############", "onCreateLoader called with id " + UPCOMING_MOVIE_LOADER_ID);
Uri baseUri = Uri.parse("https://api.themoviedb.org/3/movie/upcoming");
Log.v("############", "baseUri is " + baseUri.toString());
uriBuilder = baseUri.buildUpon();
Log.v("############", "uriBuilder is " + uriBuilder.toString());
uriBuilder.appendQueryParameter(API_KEY_PARAM, API_KEY_PARAM_VALUE);
Log.v("############", "uriBuilder.toString() is " + uriBuilder.toString());
}
return new MoviePosterLoader(getActivity().getApplicationContext(), uriBuilder.toString());
}
@Override
public void onLoadFinished(Loader<ArrayList<Movie>> loader, ArrayList<Movie> incomingMovieArrayList) {
switch (loader.getId()) {
case POPULAR_MOVIE_LOADER_ID:
Log.v("############******", "onLoadFinished called with id " + POPULAR_MOVIE_LOADER_ID);
if (incomingMovieArrayList.isEmpty()) {
Log.v("******************", "popularMovies isEmpty");
return;
} else {
popularMovies = incomingMovieArrayList;
mPopularMoviesAdapter = new PopularMoviesAdapter(getActivity(), popularMovies);
mPopularMoviesAdapter.setMovieData(popularMovies);
mPopularMovieRecyclerView.setAdapter(mPopularMoviesAdapter);
}
break;
case UPCOMING_MOVIE_LOADER_ID:
Log.v("############******", "onLoadFinished called with id " + UPCOMING_MOVIE_LOADER_ID);
if (incomingMovieArrayList.isEmpty()) {
Log.v("******************", "popularMovies isEmpty");
return;
} else {
upcomingMovies = incomingMovieArrayList;
mUpcomingMovieAdapter = new UpcomingMovieAdapter(getActivity(), upcomingMovies);
mUpcomingMovieAdapter.setMovieData(upcomingMovies);
mUpcomingMovieRecyclerView.setAdapter(mUpcomingMovieAdapter);
}
break;
}
}
@Override
public void onLoaderReset(Loader<ArrayList<Movie>> loader) {
Log.v("############******", "onLoaderReset called ");
}
}
和 正如您在下面的 Logcat 消息中看到的,问题肯定在那里。
Logcat 消息:
`首次启动应用程序时:
12-07 01:37:56.450 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:37:56.450 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is empty
12-07 01:37:56.450 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager called
12-07 01:37:56.453 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 1111
12-07 01:37:56.453 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateLoader called with id 1111
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager finished
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager called
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 9999
12-07 01:37:56.455 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager finished
12-07 01:37:56.456 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is null
12-07 01:37:56.493 9756-9756/me.abhishekraj.showmyshow V/############******: onActivityCreated called and saveInstance is null
12-07 01:37:57.683 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 9999
12-07 01:37:57.731 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 1111
After a popular movie poster is clicked
12-07 01:29:16.062 2256-2256/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
After coming back from DetailActivity
12-07 01:38:52.785 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:38:52.785 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is empty
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 1111
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateLoader called with id 1111
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager finished
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager called
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 9999
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager finished
12-07 01:38:52.851 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is null
12-07 01:38:52.855 9756-9756/me.abhishekraj.showmyshow V/############******: onActivityCreated called and saveInstance is null
12-07 01:38:53.326 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 9999
12-07 01:38:54.033 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 1111
After a upcoming movie poster is clicked
12-07 01:30:04.572 2256-2256/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
After coming back from DetailActivity
12-07 01:39:51.672 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:39:51.672 9756-9756/me.abhishekraj.showmyshow V/############******: onLoaderReset called
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is empty
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager called
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 1111
12-07 01:39:51.759 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateLoader called with id 1111
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: startPopularMoviesLoaderManager finished
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager called
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: initLoader called with id 9999
12-07 01:39:51.760 9756-9756/me.abhishekraj.showmyshow V/############******: startUpcomingMoviesLoaderManager finished
12-07 01:39:51.761 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is null
12-07 01:39:51.765 9756-9756/me.abhishekraj.showmyshow V/############******: onActivityCreated called and saveInstance is null
12-07 01:39:51.815 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 1111
12-07 01:39:51.817 9756-9756/me.abhishekraj.showmyshow V/############******: onLoadFinished called with id 9999
on rotate
12-07 01:40:18.441 9756-9756/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
12-07 01:40:18.472 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:40:18.472 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is not empty
12-07 01:40:18.478 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is Bundle[{upcomingMovies=[me.abhishekraj.showmyshow.Movie@c837a9f, me.abhishekraj.showmyshow.Movie@42b07b5, me.abhishekraj.showmyshow.Movie@da99e4a,.......and so on..that means it's not empty
onRotating back
12-07 01:40:48.244 9756-9756/me.abhishekraj.showmyshow V/############******: onSaveInstanceState called
12-07 01:40:48.281 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate called
12-07 01:40:48.281 9756-9756/me.abhishekraj.showmyshow V/############******: onCreate savedInstance is not empty
12-07 01:40:48.286 9756-9756/me.abhishekraj.showmyshow V/############******: onCreateView savedInstance is Bundle[{upcomingMovies=[me.abhishekraj.showmyshow.Movie@c837a9f, me.abhishekraj.showmyshow.Movie@42b07b5, me.abhishekraj.showmyshow.Movie@da99e4a, me.abhishekraj.showmyshow.Movie@67a86d8, me.abhishekraj.showmyshow.Movie@a516a31, me.abhishekraj.showmyshow.Movie@e241e97,.....and so on...that means it's not empty`
那问题出在哪里呢?为什么当我 return 从另一个 activity 到这个片段时我得到空白的 saveInstanceState 而不是空的 saveInstanceState 用于屏幕旋转,即使在这两种情况下再次创建 activity 也是如此(???) . 谢谢!
编辑:
如果需要更多我的代码来引用,那么可以在下面找到:Gist
如果将 main activity 的启动模式用作单顶,这个问题可以很容易地处理,这在我的用例中似乎完全可以接受。这是解决问题后我的 manifest.xml 的样子:
<activity
android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
但是,更好的方法是使用 Back Stack,这样 activity 状态可以在被销毁之前保存下来。当我使用 back-stack 解决它时,我会更新答案,但现在它完成了工作。