我正在尝试将 ListView 数据保存在 onSaveInstanceState 中。由于某种原因,当我在 onSaveInstanceState 中调用类变量时,它没有填充正确的数据。
public class ArtistTopTen extends Fragment {
private ListView artistTopTen;
private String artistId;
private Tracks listTracks;
private exposed.coding.android_nano.Adapters.ArtistTopTen topTenListAdapter;
private SpotifyApi spotifyApi;
private SpotifyService spotifyService;
private MusicPlayerDialogFragment musicPlayerDialogFragment;
public ArtistTopTen() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment_artist_top_ten, container, false);
if(getActivity().findViewById(R.id.topten_container) == null) {
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
// Start the service
getActivity().startService(new Intent(getActivity(), Music.class));
if(savedInstanceState == null) {
try {
if (getActivity().getIntent().hasExtra("id")) {
artistId = getActivity().getIntent().getStringExtra("id");
} else {
artistId = getArguments().getString("artistid");
}
} catch (Exception e) {
Log.e("ERROR", e.toString());
}
}else {
Log.e("NOTICE", "SavedInstanceState has data");
}
if(artistId != null) {
artistTopTen = (ListView) view.findViewById(R.id.artist_top_ten);
topTenListAdapter = new exposed.coding.android_nano.Adapters.ArtistTopTen(getActivity(), listTracks);
spotifyApi = new SpotifyApi();
spotifyService = spotifyApi.getService();
SharedPreferences sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
HashMap country = new HashMap<String, Object>();
if (sharedPreferences.getString("country", "us").length() != 0) {
country.put("country", sharedPreferences.getString("country", "us").toString());
} else {
country.put("country", "us");
}
spotifyService.getArtistTopTrack(artistId, country, new Callback<Tracks>() {
@Override
public void success(Tracks tracks, Response response) {
listTracks = tracks;
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
notifyAdapter();
}
});
}
@Override
public void failure(RetrofitError error) {
Toast.makeText(view.getContext(), "Somthing went wrong", Toast.LENGTH_LONG).show();
}
});
artistTopTen.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(":MediaPlayerUpdateList");
intent.putExtra("tracks", new ParcelablesTracks(listTracks, position));
getActivity().sendBroadcast(intent);
if(getActivity().findViewById(R.id.topten_container) != null) {
musicPlayerDialogFragment = new MusicPlayerDialogFragment();
musicPlayerDialogFragment.setCancelable(false);
musicPlayerDialogFragment.show(getFragmentManager(), "fragment_music_player");
}else {
intent = new Intent(getActivity(), MusicPlayerActivity.class);
intent.putExtra("returning", false);
startActivity(intent);
}
}
});
}
if(savedInstanceState != null) {
}
return view;
}
private void notifyAdapter() {
Log.e("First Track Name - SHOWING", listTracks.tracks.get(0).name);
topTenListAdapter.setListTracks(listTracks);
if(artistTopTen.getAdapter() == null) {
artistTopTen.setAdapter(topTenListAdapter);
}else {
topTenListAdapter.notifyDataSetChanged();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
Log.e("First Track Name - NOT SHOWING", listTracks.tracks.get(0).name);
//outState.putParcelable("list", new ParcelablesTracks(listTracks, 0));
super.onSaveInstanceState(outState);
}
}
如果您查看函数 notifiyAdapter(),您可以看到我正在打印歌曲的名称:
Log.e("First Track Name - SHOWING", listTracks.tracks.get(0).name);
但是,当调用 onSaveInstanceState 时,每当我尝试访问轨道时都会出错:
Log.e("First Track Name - NOT SHOWING", listTracks.tracks.get(0).name);
错误:
07-16 10:12:07.759 29091-29091/exposed.coding.android_nano E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: exposed.coding.android_nano, PID: 29091
java.lang.NullPointerException: Attempt to read from field 'java.util.List kaaes.spotify.webapi.android.models.Tracks.tracks' on a null object reference
at exposed.coding.android_nano.Fragments.ArtistTopTen.onSaveInstanceState(ArtistTopTen.java:162)
at android.app.Fragment.performSaveInstanceState(Fragment.java:2198)
at android.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1605)
at android.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1662)
at android.app.Activity.onSaveInstanceState(Activity.java:1367)
at android.app.Activity.performSaveInstanceState(Activity.java:1298)
at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1288)
at android.app.ActivityThread.callCallActivityOnSaveInstanceState(ActivityThread.java:3961)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3924)
at android.app.ActivityThread.access$900(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
我对 Android 开发还很陌生,但我正在使用相同的过程将数据保存在另一个 fragment 中,并且它工作得很好。我不确定这里发生了什么。
仓库:https://github.com/Bioto/Android-Nano-Degree-Project1.2
编辑:
设置列表轨道:
E/Setting listTracks﹕ ArtistTopTen{98c918d #2 id=0x7f0c0051}
onSaveInstanceState:
E/onSaveInstanceState()﹕ ArtistTopTen{3b7de284 #1 id=0x7f0c0051}
最佳答案
编辑:所以似乎发生的情况是接收响应的 Fragment 实例与保存其状态的 Fragment 实例不同。这可能是由于您处理 Spotify 请求的回调的方式所致。
我认为正在发生的事情的总体思路是:
- fragment 98c918d 已创建
- 使用回调的匿名实现将请求发送到请求轨道,该回调保存对 fragment 98c918d 的引用。
- 发生配置更改(屏幕旋转),并且 fragment 98c918d 被破坏。
- 已创建 fragment (3b7de284) 的新实例。
- 请求完成, fragment 98c918d 收到结果。
- 发生另一次配置更改,3b7de284 尝试保存其状态,但实际上没有数据。
因此,您实际上看到的是内存泄漏(旧的 Fragment 一直保留到请求完成为止)。我建议研究 Loader
框架来处理跨配置更改的网络请求。或者,将该工作放入 IntentService
中,在加载后保留轨道,然后广播该事件。如果 Fragment 仍然存在并接收到广播,则它可以加载新结果。否则,当接下来调用 onStart() 或 onResume() 时,它可以查找任何现有结果(可能在 fragment 未监听时已加载)。
Attempt to read from field 'java.util.List kaaes.spotify.webapi.android.models.Tracks.tracks' on a null object reference
listTracks
为空。因此调用listTracks.tracks
将导致NullPointerException
。似乎在某些情况下,listTracks
从未被分配(它仅在 getArtistTopTracks()
的 success()
方法中分配,所以如果由于任何原因失败,它永远不会被分配。在这种情况下,将该行包装在空检查中可能就足够了;即:
if (listTracks != null) {
// do stuff with listTracks
}
关于java - Android onSaveInstanceState 未获取类变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31460567/