首先庆祝一下本人博客满一年,求撒花!

众所周知,根据mvc设计模式,数据是要通过model来传递的,从一个activity(以下简称A)到另外一个activity(以下简称B)如果要传值的话我们可以将model放到intent中(也可以不放),然后在B创建之后取得相应的值;反之,如果从B回传值给A的话,也是可行的,只不过要在A的onActivityResult中接收相应的值。这几种方法各有优缺点,大家自己可以结合实际情况来选择。
本文的中心思想交代完毕,下面就开始看具体的代码演示吧。
一、通过model传值

  • 直接通过model传值
    这种方法非常简单,我们可以通过新建一个数据源单例DataSource,然后将所有的model都放在里面,需要传值的时候直接给model赋值即可。
    以下展示数据源DataSource核心代码:
public class DataSource {
    public Job job;

    private static DataSource instanceDataSource;
    public static DataSource shareInstance(){
        if (null == instanceDataSource) {
            instanceDataSource = new DataSource();
        }
        return instanceDataSource;
    }
}

好,假设我们现在有一个工作列表页(JobActivity,图一)和工作详情页(JobDetailActivity,图二),最常见的情形莫过于选择列表页的某个item,进入详情页。那么传值的话核心代码如下:

android serializable 传值 安卓传值_设计模式


android serializable 传值 安卓传值_mvc_02

//位于JobActivity中,点击列表页的某项,相应了listview的onItemClick方法
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent intent = new Intent();
        //mJobs这个成员变量是Listview的数据来源,给数据源的某个model(即job)赋值,由于datasource 是单例,所有的成员变量一旦赋值,就会常驻内存,不会变化,因此传递的值是不会变化的
        DataSource.shareInstance().job = JobActivity.this.mJobs.get(position);
        intent.setClass(this, JobDetailActivity.class);
        this.startActivity(intent);
    }

以下是接受值的核心代码

//位于JobDetailActivity中,在oncreate方法中
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_job_detail);
        //取得相应的model
        Job job = DataSource.shareInstance().job;
        //虽然多此一举,但还是做个判断吧,哈哈!
        if (null != job) {
            titleTextView = (TextView) findViewById(R.id.jobdetail_title_textview);
            titleTextView.setText(null != job.jobName ? job.jobName : "");
            areaTextView = (TextView) findViewById(R.id.jobdetail_area_textview);
            areaTextView.setText(null != job.workArea ? job.workArea : "");
            salaryTextViearw = (TextView) findViewById(R.id.jobdetail_salary_textview);
            salaryTextViearw.setText(null != job.workSalary ? job.workSalary : "");
            companyTextView = (TextView) findViewById(R.id.jobdetail_company_textview);
            companyTextView.setText(null != job.workCompany ? job.workCompany : "");
            contactTextView = (TextView) findViewById(R.id.jobdetail_contact_textview);
            contactTextView.setText(null != job.workContact ? job.workContact : "");
        }
}

这种传值方式最大的优势就是通俗易懂,简单粗暴。而且确实是使用了mvc设计模式的,最主要的是可以实现双向传值,也就是从A到B可以传递,从B到A也可以,相当方便,是进阶优秀程序员的必备方法,缺点也是有的:
(1),对象常驻内存,如果遇到大的model的话会比较吃内存(当然,也可以通过及时设置model为null来解决这个问题。)
(2)因为DataSource是单例,多线程肯定是要考虑的问题了。本文为了演示方便,没有考虑并发的情况。但开发中就必须要考虑了,试想一种情况,主线程在获取job对象后,后台我们启动的某个线程在更改job对象的值,然后呢。。。。。数据肯定是会出问题了!总而言之,这是考验阁下技术的最好的传值方法。

  • 将model设置到Intent中传值

Android 的设计人员命名总是让人有些摸不透,比如页面不像ios一样叫controller,也不叫page,而是叫Activity。两个Activity传值的类取名intent,也就是“意图”的意思,实在不知道他们的“意图”是什么。
废话少说,直接上核心代码:
intent传递model的核心方法是:

Intent  putExtra(String name, Bundle value)

这个bundle就是我们将要传递的对象了
首先,我们要序列化我们的Job对象:

//job类后面的 implements Serializable两个关键字就是序列化!
public class Job implements Serializable{

    public String jobName;
    public String jobId;
    public String workArea;
    public String workTime;
    public String workSalary;
    public String workDescription;
    public String workCompany;
    public String workContact;
    public String poster;

}

下面开始传值啦!

Intent intent = new Intent(this,JobDetailActivity.class);  
        Bundle bundle = new Bundle();
        //job对象是之前序列化了的对象  
        bundle.putParcelable(PAR_KEY, job);  
        intent.putExtras(bundle);

第二种方法演示完毕,不知大家看了以后有没有什么感受,是不是感觉没有第一种爽?但还可以啦,凑合凑合看看吧,继续往下就更麻烦了,继续遵循我们的由易到难原则往下看吧!

二、通过intent回传值

1.回传值不管在ios或者Android上都是相对来说比较麻烦的,ios中初期通过代理传递,后期如果技术可以了,您可以直接把传值跟传递控制权分开来玩耍,很带感!
Android中回传值涉及到两个方法

startActivityForResult() 
onActivityResult()

设想一个场景,JobActivity中要实现根据地区筛选工作,那么你就得有一个地区选择页面(AreaSelectActivity,见图三),选择地区回来后重新刷新Listview来加载相应地区的工作。

android serializable 传值 安卓传值_设计模式_03


所以,我们要在用户在AreaSelectActivity上选择地区后把AreaSelectActivity这个页面finish掉,然后告诉JobActivity用户选择了某个地区,需要把所有这个地区的工作过滤出来。

好了,背景交代完毕,接下来开始动手吧。

1.在JobActivity的filter按钮点击后编写如下代码:

public void onClick(View v) {
        switch (v.getId()) {
        //id为job_area_button的button是如图一所示的filter按钮
        case R.id.job_area_button: {
            Intent intent = new Intent();
            //设置要跳转的activity
            intent.setClass(this, AreaSelectActivity.class);
            //这句话很关键,就是之前我交代的两个方法中的第一个,区别于startActivity方法的是,他告诉编译器,我这个页面是要接受下一个页面的回传值的。RESULT_CODE_AREASELECT是我自己写的常量,大家可以用任何整型变量代替
            startActivityForResult(intent, RESULT_CODE_AREASELECT);
        }

            break;
        }
}

2.在AreaSelectActivity这个activity中点击某个item后编写如下代码:

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        switch (parent.getId()) {
        //这个id位area_all_listview的是AreaSelectActivity的listview
        case R.id.area_all_listview: {
            Intent intent = new Intent(this,JobActivity.class);
            intent.putExtra("position", position);
            //关键是这句话,他告诉前一个activity(也就是JobActivity)我这边设置了一个tag,RESULT_OK,用来区分是哪一个activity传递过来的值(因为可以JobActivity可能要接受多个activity的回传值)
            setResult(RESULT_OK, intent);
            this.finish();
        }
            break;
        }
}

3.在JobActivity中接受回传值:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (JobActivity.RESULT_CODE_AREASELECT == requestCode) {
            if (null == data) {
                return;
            }
            int position = data.getIntExtra("position", 0);
            System.out.println("postion:" + position);
        }
}

先解释一下onActivityResult中的几个参数的意思吧,
(1)requestCode:不言而喻,就是请求码,也就是我之前设置的常量RESULT_CODE_AREASELECT
(2)resultCode:不多说,就是返回码,也就是RESULT_OK了
(3)data:传过来的数据,使用intent封装好的。
所以呢,我们就先判断这个请求码是不是
JobActivity.RESULT_CODE_AREASELECT
如果是的话,就说明是AreaSelectActivity回传回来的,那我们的逻辑就在里面写了。取到里面的intent中的position即可。

好了,所有的传值方法都介绍完毕了,好累啊,欢迎大家多多交流!