发布实施 Parcelable 和检索自定义对象

Issue Implementing Parcelable and retriving custom object

我一直在尝试将 Parcelable 实现到我的自定义对象中,以便在活动之间发送和检索它。但是,应用程序在设置对象的值时崩溃,但我不明白为什么。控制台输出如下:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.musicalstructureapp, PID: 10537
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.musicalstructureapp/com.example.musicalstructureapp.MusicPlayerActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.musicalstructureapp.Songs.getArtist()' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3792)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:246)
    at android.app.ActivityThread.main(ActivityThread.java:8506)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.musicalstructureapp.Songs.getArtist()' on a null object reference
    at com.example.musicalstructureapp.MusicPlayerActivity.onCreate(MusicPlayerActivity.java:21)
    at android.app.Activity.performCreate(Activity.java:8198)
    at android.app.Activity.performCreate(Activity.java:8182)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3765)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3968) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:246) 
    at android.app.ActivityThread.main(ActivityThread.java:8506) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130) 

这个输出是什么意思?

Attempt to invoke virtual method 'java.lang.String com.example.musicalstructureapp.Songs.getArtist()' on a null object reference

我是这样实现 Parcelable 的:

package com.example.musicalstructureapp;
import android.os.Parcel;
import android.os.Parcelable;

public class Songs implements Parcelable {

/**
 * Artist's name.
 */
private String mArtist;

/**
 * Album name.
 */
private String mAlbum;

/**
 * Track name.
 */
private String mTrack;

/**
 * Track name.
 */
private int mCover;

/**
 * Create a new Song object.
 *
 * @param artist is the artist's name.
 * @param album  is the name of the album.
 * @param track  is the name of the track.
 */
public Songs(String artist, String album, String track, int cover) {
    mArtist = artist;
    mAlbum = album;
    mTrack = track;
    mCover = cover;
}

/**
 * Get the artist's name.
 */
public String getArtist() {
    return mArtist;
}

/**
 * Get the album name.
 */
public String getAlbum() {
    return mAlbum;
}

/**
 * Get the track name.
 */
public String getTrack() {
    return mTrack;
}

/**
 * Get the cover of the album.
 */
public int getCover() {
    return mCover;
}

@Override
public int describeContents() {
    return 0;
}

/**
 * Write object's data to the passed-in Parcel.
 */
@Override
public void writeToParcel(Parcel parcel, int i) {
    parcel.writeString(mArtist);
    parcel.writeString(mAlbum);
    parcel.writeString(mTrack);
    parcel.writeInt(mCover);
}

/**
 * This is used to regenerate the object.
 */
public static final Parcelable.Creator<Songs> CREATOR = new Parcelable.Creator<Songs>() {
    public Songs createFromParcel(Parcel in) {
        return new Songs(in);
    }

    public Songs[] newArray(int size) {
        return new Songs[size];
    }
};

private Songs(Parcel in) {
    mArtist = in.readString();
    mAlbum = in.readString();
    mTrack = in.readString();
    mCover = in.readInt();
}
}

我的 TracksActivity 包含对象列表并使用 onItemClickListener 打开新的 activity 并传递对象:

package com.example.musicalstructureapp;

import android.content.Intent;
import android.os.Bundle;
import android.widget.ListView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;

public class TracksActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_tracks);

    // New list of songs
    ArrayList<Songs> songs = new ArrayList<>();
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_one), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_two), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_three), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_four), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_five), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_six), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_seven), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_eight), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_nine), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_ten), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_eleven), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_twelve), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_thirteen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_fourteen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_fifteen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_sixteen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_seventeen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_eighteen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_nineteen), R.drawable.cover_sample));
    songs.add(new Songs(getString(R.string.NF), getString(R.string.the_search), getString(R.string.track_twenty), R.drawable.cover_sample));

    // Create an SongAdapter, whose data source is a list of Songs. The adapter knows how to create list items for each item in the list.
    SongAdapter adapter = new SongAdapter(this, songs);

    // Find the ListView object in the view hierarchy of the Activity.
    // There should be a ListView with the view ID called activity_tracks_list_view, which is declared in the
    // activity_tracks.xml layout file.
    ListView listView = findViewById(R.id.activity_tracks_list_view);

    // Make the ListView use the SongAdapter we created above, so that the
    // ListView will display list items for each Songs in the list.
    listView.setAdapter(adapter);

    // Open new Activity on click. Passes clicked object to MusicPlayerActivity.
    listView.setOnItemClickListener((parent, view, position, id) -> {
        Intent openPlayer = new Intent(TracksActivity.this, MusicPlayerActivity.class);
        openPlayer.putExtra("song", position);
        startActivity(openPlayer);
    });

}
}

activity我要取回传过来的对象:

package com.example.musicalstructureapp;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

public class MusicPlayerActivity extends TracksActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music_player);

    Intent passedIntent = getIntent();
    Songs song = (Songs) passedIntent.getParcelableExtra("song");

    TextView currentArtist = findViewById(R.id.currentArtistName_text_view);
    TextView currentTrack = findViewById(R.id.currentTrackName_text_view);
    TextView currentAlbum = findViewById(R.id.currentAlbumName_text_view);
    ImageView currentCover = findViewById(R.id.currentAlbumCover_image_view);

    currentArtist.setText(song.getArtist());
    currentTrack.setText(song.getTrack());
    currentAlbum.setText(song.getAlbum());
    currentCover.setImageResource(song.getCover());

}
}

openPlayer.putExtra("song", position);更改为openPlayer.putExtra("song", songs.get(position));

现在您正在将 int(position 是 int)值发送到您的 MusicPlayerActivity 并将其投射到 Songs。因此在 currentArtist.setText(song.getArtist()); 你得到 nullpointerexception.