简体   繁体   English

Android Parcelable对象在活动之间无法正常传递

[英]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. 奇怪的是,在将一个对象从activity传递给fragment时,代码在一个项目中运行正常,但是我无法使该对象从activity转到activity,即使我似乎正在实现parcelable。

Oddly, I don't get a null object at the other end, but the object has got null values within it. 奇怪的是,我没有在另一端获得一个null对象,但该对象在其中有空值。

I've created a new project to test this with. 我已经创建了一个新项目来测试它。 This is the code so far: 这是到目前为止的代码:

MainActivity.java: 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: 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: 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: 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. 我期望的是,“hi”值出现在两次,一次是在我启动应用程序时,再次是当我单击按钮并且新活动创建时。

However, it's only showing correctly the first time, the second time the getSiteName only returns null. 但是,它仅在第一次正确显示时,第二次getSiteName仅返回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; 我还直接从工作应用程序复制并粘贴了Site对象,结果相同,但它可以在工作应用程序中按预期工作; the Site object is copied properly. Site对象被正确复制。

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. 问题出在Parcelable的实现上。 siteName is never written to the parcel, and you are writing mData instead, which is never used anywhere. siteName永远不会写入parcel,而是编写mData,它从不在任何地方使用。 You can keep mData if you need it, and ADD writes for siteName, see the code: 如果需要,可以保留mData,并为siteName添加ADD写入,请参阅代码:

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: 像bundle对象一样接收它:

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: 在activity2中,在onCreate()中,您可以通过检索bundle(包含调用活动发送的所有消息)来获取String消息/对象并调用:

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

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

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