发送Parcelable []作为Intent extra时发生java.lang.ClassCastException

时间:2017-03-13 11:09:40

标签: android android-intent

我发送一个TutorAccount数组作为另一个Activity的额外意图。以下是涉及的TutorAccount和Account类:

public class TutorAccount extends Account{

    public TutorAccount(TutorProfile profile) {
        super(profile);
    }

    public TutorAccount(TutorProfile profile, LocationInfo locationInfo) {
        super(profile, locationInfo);
    }

    public TutorProfile getProfile() {
        return (TutorProfile) super.getProfile();
    }

    public void setProfile(TutorProfile profile) {
        super.setProfile(profile);
    }
}

和帐户类

public class Account implements Parcelable {

    /**Email Id of the User */
    private String mEmailID;

    /**Important to have the status indexed as this shall be used during a query for a particular user type*/
    private Integer accountStatus;

    // Profile info.
    private GenericLearnerProfile profile;

    // Tutor's location info. - this would be computed from {Latitude, Longitude} which shall be available
    // from the _1 info. Also, this holds a reference to the LatLng{Latitude, Longitude} from the _1.
    private LocationInfo locationInfo;

    public Account(GenericLearnerProfile profile) {
        if(profile == null){
            throw new NullPointerException("Profile can't be null");
        }
        this.profile = profile;
        mEmailID = profile.getEmailID();
        // Auto boxing
        this.accountStatus = profile.getCurrentStatus();
    }

    public Account(GenericLearnerProfile profile, LocationInfo locationInfo) {
        if(profile == null){
            throw new NullPointerException("Profile can't be null");
        }
        this.profile = profile;
        this.locationInfo = locationInfo;

        mEmailID = profile.getEmailID();

        this.accountStatus = profile.getCurrentStatus();
    }

    private Account(){

    }

    public GenericLearnerProfile getProfile() {
        return profile;
    }

    public void setProfile(GenericLearnerProfile profile) {
        if(profile == null){
            throw new NullPointerException("Profile can't be null");
        }
        this.profile = profile;
        mEmailID = profile.getEmailID();
    }

    public LocationInfo getLocationInfo() {
        return locationInfo;
    }

    public void setLocationInfo(LocationInfo locationInfo) {
        this.locationInfo = locationInfo;
    }

    public static class LocationInfo implements Parcelable {
        private String shortFormattedAddress;

        public LocationInfo(String shortFormattedAddress) {
            this.shortFormattedAddress = shortFormattedAddress;
        }

        public String getShortFormattedAddress() {
            return shortFormattedAddress;
        }

        public void setShortFormattedAddress(String shortFormattedAddress) {
            this.shortFormattedAddress = shortFormattedAddress;
        }

        protected LocationInfo(Parcel in) {
            shortFormattedAddress = in.readString();
        }

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

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(shortFormattedAddress);
        }

        @SuppressWarnings("unused")
        public static final Parcelable.Creator<LocationInfo> CREATOR = new Parcelable.Creator<LocationInfo>() {
            @Override
            public LocationInfo createFromParcel(Parcel in) {
                return new LocationInfo(in);
            }

            @Override
            public LocationInfo[] newArray(int size) {
                return new LocationInfo[size];
            }
        };
    }

    protected Account(Parcel in) {
        mEmailID = in.readString();
        accountStatus = in.readByte() == 0x00 ? null : in.readInt();
        profile = (GenericLearnerProfile) in.readValue(GenericLearnerProfile.class.getClassLoader());
        locationInfo = (LocationInfo) in.readValue(LocationInfo.class.getClassLoader());
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mEmailID);
        if (accountStatus == null) {
            dest.writeByte((byte) (0x00));
        } else {
            dest.writeByte((byte) (0x01));
            dest.writeInt(accountStatus);
        }
        dest.writeValue(profile);
        dest.writeValue(locationInfo);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Account> CREATOR = new Parcelable.Creator<Account>() {
        @Override
        public Account createFromParcel(Parcel in) {
            return new Account(in);
        }

        @Override
        public Account[] newArray(int size) {
            return new Account[size];
        }
    };
}

您可以看到TutorAccount延伸Account。这是异常的堆栈跟踪:

java.lang.ClassCastException: com.learncity.generic.learner.account.Account cannot be cast to com.learncity.tutor.account.TutorAccount
                      at com.learncity.learner.search.SearchResultsActivity.onCreate(SearchResultsActivity.java:48)
                      at android.app.Activity.performCreate(Activity.java:6662)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
                      at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6077) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

这是说帐户无法投放到TutorAccount。我不确定Account是如何投射出来的,因为它应该是Tutorlable to TutorAccount cast。

以下是用于发送和接收Intent extra的代码:

发送活动

// Show these accounts in a list view
Intent i = new Intent(this, SearchResultsActivity.class);
i.putExtra(SEARCHED_ACCOUNTS, refactorAccountsToArray(accounts));
startActivity(i);

接收活动

List<TutorAccount> list = new ArrayList<>(10);
        for(Parcelable p : getIntent ().getParcelableArrayExtra(SEARCHED_ACCOUNTS)){
            list.add((TutorAccount)p);
        }

我尝试在接收活动中记录p - Parcelable,它显示它是Account的一个实例。我不确定这是怎么回事。有没有人遇到过这个?

修改

我在这里的参数中收到的List<TutorAccount> accounts是一个不同的类来模拟后端JSON数据。

以下是refactorAccountsToArray()方法:

private List<com.learncity.tutor.account.TutorAccount> refactorAccountsToList(List<TutorAccount> accounts){
        // Extract the list of accounts from backend
        List<TutorProfileVer1> profiles = new ArrayList<TutorProfileVer1>();
        List<Account.LocationInfo> locationInfos = new ArrayList<Account.LocationInfo>();
        for(TutorAccount acc : accounts){
            profiles.add(acc.getProfile());
            locationInfos.add(new Account.LocationInfo((acc.getLocationInfo() == null ? null: acc.getLocationInfo().getShortFormattedAddress())));
        }

        // Populate a profile model
        List<com.learncity.tutor.account.TutorAccount> acc = new ArrayList<com.learncity.tutor.account.TutorAccount>();
        List<TutorProfile> refactoredProfiles = TutorProfile.populateProfilesFromEntities(profiles);
        int i = 0;
        for(TutorProfile p : refactoredProfiles){
            com.learncity.tutor.account.TutorAccount t = new com.learncity.tutor.account.TutorAccount(p);
            t.setLocationInfo(new Account.LocationInfo(locationInfos.get(i).getShortFormattedAddress()));
            acc.add(t);
            i++;
        }
        return acc;
    }

    private com.learncity.tutor.account.TutorAccount[] refactorAccountsToArray(List<TutorAccount> accounts){

        List<com.learncity.tutor.account.TutorAccount> refactoredProfiles = refactorAccountsToList(accounts);
        return refactoredProfiles.toArray(new com.learncity.tutor.account.TutorAccount[refactoredProfiles.size()]);
    }

1 个答案:

答案 0 :(得分:0)

根据 @AnhaytAnanun 的建议结果表明,即使是演员,也需要一个Parcelable实体的创建者。我的代码现在可以使用CREATOR和其他Parcelable方法。以下是修订后的代码:

package com.learncity.tutor.account;

import android.os.Parcel;
import android.os.Parcelable;

import com.learncity.generic.learner.account.Account;
import com.learncity.tutor.account.profile.model.TutorProfile;

/**
 * Created by DJ on 3/7/2017.
 */

public class TutorAccount extends Account{

    public TutorAccount(TutorProfile profile) {
        super(profile);
    }

    public TutorAccount(TutorProfile profile, LocationInfo locationInfo) {
        super(profile, locationInfo);
    }

    public TutorProfile getProfile() {
        return (TutorProfile) super.getProfile();
    }

    public void setProfile(TutorProfile profile) {
        super.setProfile(profile);
    }

    public TutorAccount(Parcel in) {
        super(in);
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<TutorAccount> CREATOR = new Parcelable.Creator<TutorAccount>() {
        @Override
        public TutorAccount createFromParcel(Parcel in) {
            return new TutorAccount(in);
        }

        @Override
        public TutorAccount[] newArray(int size) {
            return new TutorAccount[size];
        }
    };
}