简体   繁体   中英

Android Parcelable object not passing properly between activities

This has been taxing my mind for the past two days. Oddly, the code works fine in one project, when passing an object from activity to fragment, but I cannot make this object pass from activity to activity, even when I appear to be implementing parcelable properly.

Oddly, I don't get a null object at the other end, but the object has got null values within it.

I've created a new project to test this with. This is the code so far:

MainActivity.java:

    package com.example.parcleableexample;

    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Intent;
    import android.view.Menu;
    import android.view.View;
    import android.widget.TextView;

    public class MainActivity extends Activity {
        Site mySite = new Site();


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mySite.setSiteName("hi");
            TextView myText = (TextView) findViewById(R.id.txtSiteName);
            myText.setText(mySite.getSiteName());
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }


        public void doThing (View v) {
            Intent mIntent = new Intent(this,AnotherActivity.class);
            mIntent.putExtra("site", mySite);
            startActivity(mIntent);
        }
    }

AnotherActivity.java:

package com.example.parcleableexample;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class AnotherActivity extends Activity {

    Site mySite = new Site();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mySite = getIntent().getParcelableExtra("site");
            TextView myText = (TextView) findViewById(R.id.txtSiteName);
            myText.setText(mySite.getSiteName());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

Site.Java:

package com.example.parcleableexample;

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

public class Site implements Parcelable {

    private String siteName;

    Site() {
        // Empty Constructor
    }

    public String getSiteName() {
        return siteName;
    }

    public void setSiteName(String siteName) {
        this.siteName = siteName;
    }

    // Parcleable Functions:
    private int mData;
    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
    }

    public static final Parcelable.Creator<Site> CREATOR = new Parcelable.Creator<Site>() {
        public Site createFromParcel(Parcel in) {
            return new Site(in);
        }

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

    private Site(Parcel in) {
        mData = in.readInt();
    }
}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/txtSiteName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/txtSiteName"
        android:layout_below="@+id/txtSiteName"
        android:layout_marginLeft="42dp"
        android:layout_marginTop="25dp"
        android:onClick="doThing"
        android:text="Button" />

</RelativeLayout>

What I would expect, is for the "hi" value to appear both times, once when I start the app, and again when I click the button and the new activity creates.

However, it's only showing correctly the first time, the second time the getSiteName only returns null.

I also copied and pasted the Site object directly from the working app, with the same result, but it works in the working app as expected; the Site object is copied properly.

The working app runs this code:

Bundle arguments = new Bundle();
arguments.putParcelable("site", SearchResults.get(position));
ViewSiteFragment myFragment = new ViewSiteFragment();
myFragment.setArguments(arguments);
FragmentTransaction myTransaction = getFragmentManager().beginTransaction();
myTransaction.replace(R.id.MainFragmentContainer, myFragment);
myTransaction.addToBackStack(null);
myTransaction.commit();

And picks up the object at the other end here:

Site mSite = getArguments().getParcelable("site");

I know I'm doing something wrong... Just haven't got a clue what I've missed!

The problem is in your implementation of Parcelable. siteName is never written to the parcel, and you are writing mData instead, which is never used anywhere. You can keep mData if you need it, and ADD writes for siteName, see the code:

public void writeToParcel(Parcel out, int flags) {
    out.writeInt(mData);

    //we want to keep siteName in our parcel, so let's write it to the Parcel obj
    out.writeString(siteName);
}

Later, add this code to read from parcel:

private Site(Parcel in) {
    mData = in.readInt();

    //let's read from in Parcel an set our siteName
    siteName = in.readString();
}

Receive it like this with bundle object:

In activity2, in onCreate(), you can get the String message/object by retrieving a bundle (which contains all the messages sent by the calling activity) and call:

Bundle bundle = getIntent().getExtras();
mySite = bundle.getParcelableExtra("site");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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