繁体   English   中英

Android onSaveInstanceState没有获取类变量

[英]Android onSaveInstanceState not getting class variables

我试图将我的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开发很陌生,但是我正在使用相同的过程将数据保存到另一个片段中,并且工作正常。 我不确定这里发生了什么。

回购: 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实例与保存其状态的那个实例不同。 这可能是由于您如何处理Spotify请求的回调。

我认为正在发生的事情的总体思路是:

  1. 片段98c918d已创建
  2. 使用包含对片段98c918d的引用的Callback的匿名实现,将请求发送到请求轨道。
  3. 发生配置更改(屏幕旋转),并且片段98c918d被破坏。
  4. 创建了片段(3b7de284)的新实例。
  5. 请求完成,并且片段98c918d接收到结果。
  6. 发生另一个配置更改,并且3b7de284尝试保存其状态,但实际上没有数据。

因此,您实际上看到的是内存泄漏(旧的Fragment保留在该内存中,直到请求完成)。 我建议研究一下Loader框架来处理跨配置更改的网络请求。 或者,将其放入IntentService ,在轨道加载后保留它们,并广播事件。 如果“片段”仍在附近并接收广播,则它可以加载新结果。 否则,下一次涉及onStart()或onResume()时,它可以查找任何现有结果(可能是在片段未监听时已加载的结果)。


尝试从null对象引用上的字段'java.util.List kaaes.spotify.webapi.android.models.Tracks.tracks'中读取

listTracks为空。 因此,调用listTracks.tracks将导致NullPointerException 在某些情况下, listTracks从未分配过listTracks (仅在您的getArtistTopTracks() success()方法中分配了getArtistTopTracks() ,因此,如果由于任何原因而失败,则永远不会分配它。在这种情况下,将其包装起来就足够了空检查中的一行;即:

if (listTracks != null) {
    // do stuff with listTracks
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM