手记

Android开发必看-详解Activity之间的数据传递

Activity单向数据传递

下面的;例子演示了从 OriginActivity activity 传递字符串“some data!” 到DestinationActivity activity.
注:这是两个活动之间发送数据的最直接的方法。

直接上代码(简单粗暴直接代码示例!)
OriginActivity

public class OriginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_origin);

        // Create a new Intent object, containing DestinationActivity as target Activity.
        final Intent intent = new Intent(this, DestinationActivity.class);

        // Add data in the form of key/value pairs to the intent object by using putExtra()
        intent.putExtra(DestinationActivity.EXTRA_DATA, "Some data!");

        // Start the target Activity with the intent object
        startActivity(intent);
    }
} 
DestinationActivity

public class DestinationActivity extends AppCompatActivity {

    public static final String EXTRA_DATA = "EXTRA_DATA";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_destination);

        // getIntent() returns the Intent object which was used to start this Activity
        final Intent intent = getIntent();

        // Retrieve the data from the intent object by using the same key that
        // was previously used to add data to the intent object in OriginActivity.
        final String data = intent.getStringExtra(EXTRA_DATA);
    }
}
其他的数据类型

对于其他的数据基本类型传递也是可以的,调用intent。putExtra(key,value);但是取值时候要注明相应类型,比如传入的String,取值时候是getStringExtra()以此类推。

传递对象

有两种方式

Serializable

Serializable这种方式直接实现Serializable接口,剩下的系统会帮我们做好。

代码如下(简单粗暴直接代码示例!)

intent.putExtra(DestinationActivity.EXTRA_DATA, myParcelableObject);

bundle.putParcelable(DestinationActivity.EXTRA_DATA, myParcelableObject);

final MyParcelableType data = intent.getParcelableExtra(EXTRA_DATA); 
Parcelable

Parcelable是一个Android特定的接口,可以对自定义数据类型实现的(即你自己的对象/ POJO对象)。它是Android提供的,比Serializable更加高效。

代码如下(简单粗暴直接代码示例!)

bundle.putSerializable(DestinationActivity.EXTRA_DATA, mySerializableObject);

final SerializableType data = (SerializableType)bundle.getSerializable(EXTRA_DATA); 
Parcelable代码示例(依旧粗暴)

public class Foo implements Parcelable
{
    private final int myFirstVariable;
    private final String mySecondVariable;
    private final long myThirdVariable;

    public Foo(int myFirstVariable, String mySecondVariable, long myThirdVariable)
    {
        this.myFirstVariable = myFirstVariable;
        this.mySecondVariable = mySecondVariable;
        this.myThirdVariable = myThirdVariable;
    }

    // Note that you MUST read values from the parcel IN THE SAME ORDER that
    // values were WRITTEN to the parcel! This method is our own custom method
    // to instantiate our object from a Parcel. It is used in the Parcelable.Creator variable we declare below.
    public Foo(Parcel in)
    {
        this.myFirstVariable = in.readInt();
        this.mySecondVariable = in.readString();
        this.myThirdVariable = in.readLong();
    }

    // The describe contents method can normally return 0. It's used when
    // the parceled object includes a file descriptor.
    @Override
    public int describeContents()
    {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags)
    {
        dest.writeInt(myFirstVariable);
        dest.writeString(mySecondVariable);
        dest.writeLong(myThirdVariable);
    }

    // Note that this seemingly random field IS NOT OPTIONAL. The system will
    // look for this variable using reflection in order to instantiate your
    // parceled object when read from an Intent.
    public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>()
    {
        // This method is used to actually instantiate our custom object
        // from the Parcel. Convention dictates we make a new constructor that
        // takes the parcel in as its only argument.
        public Foo createFromParcel(Parcel in)
        {
            return new Foo(in);
        }

        // This method is used to make an array of your custom object.
        // Declaring a new array with the provided size is usually enough.
        public Foo[] newArray(int size)
        {
            return new Foo[size];
        }
    };
}
Activty之间传递数据并且返回
举个栗子

MainActivity向DetailActivity传递数据,并且等待返回,MainActivity需要重写 onActivityResult(int requestCode, int resultCode, Intent data)方法,其中requestCode用于唯一标识请求的是DetailActivity,resultCode代表是请求的状态

粗暴的代码示例
MainActivity:

public class MainActivity extends Activity {

    // Use a unique request code for each use case 
    private static final int REQUEST_CODE_EXAMPLE = 0x9345; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Create an Intent to start DetailActivity
        final Intent intent = new Intent(this, DetailActivity.class);

        // Start DetailActivity with the request code
        startActivityForResult(intent, REQUEST_CODE_EXAMPLE);
    }

    // onActivityResult only get called 
    // when the other Activity previously started using startActivityForResult
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // First we need to check if the requestCode matches the one we used.
        if(requestCode == REQUEST_CODE_EXAMPLE) {

            // The resultCode is set by the DetailActivity
            // By convention RESULT_OK means that whatever
            // DetailActivity did was executed successfully
            if(resultCode == Activity.RESULT_OK) {
                // Get the result from the returned Intent
                final String result = data.getStringExtra(DetailActivity.EXTRA_DATA);

                // Use the data - in this case, display it in a Toast.
                Toast.makeText(this, "Result: " + result, Toast.LENGTH_LONG).show();
            } else {
                // setResult wasn't successfully executed by DetailActivity 
                // Due to some error or flow of control. No data to retrieve.
            }
        }
    }
}
DetailActivity:

public class DetailActivity extends Activity {

    // Constant used to identify data sent between Activities.
    public static final String EXTRA_DATA = "EXTRA_DATA";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);

        final Button button = (Button) findViewById(R.id.button);
        // When this button is clicked we want to return a result
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Create a new Intent object as container for the result
                final Intent data = new Intent();

                // Add the required data to be returned to the MainActivity
                data.putExtra(EXTRA_DATA, "Some interesting data!");

                // Set the resultCode as Activity.RESULT_OK to 
                // indicate a success and attach the Intent
                // which contains our result data
                setResult(Activity.RESULT_OK, data); 

                // With finish() we close the DetailActivity to 
                // return back to MainActivity
                finish();
            }
        });
    }

    @Override
    public void onBackPressed() {
        // When the user hits the back button set the resultCode 
        // as Activity.RESULT_CANCELED to indicate a failure
        setResult(Activity.RESULT_CANCELED);
        super.onBackPressed();
    }
}
注意事项

1.数据会立即返回,在调用finish()之后,所以setResult()方法需要在finish()之前调用,否否则数据不会返回。

2.确定你的Activity没有使用android:launchMode="singleTask”启动模式,否则他会在一个单独的task,这样数据也不会返回。如果你的Activity使用singleTask启动,那么会立即调用onActivityResult(),并且返回result code o是Activity.RESULT_CANCELED.

3.谨慎的使用android:launchMode="singleInstance”.在 Lollipop (Android 5.0, API Level 21)之前,不会返回数据。

2人推荐
随时随地看视频
慕课网APP

热门评论

上次我遇到了这么一个场景,展示sd卡里的文件,然后点击sd卡里的某个文件 然后返回这个文件的路径跳转到最初始的界面

还是有一些坑的,总结了一下,欢迎补充

查看全部评论