论Android中的值传递

来源:互联网 发布:自然排名优化的方法 编辑:程序博客网 时间:2024/06/05 05:32

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

众所周知,根据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,进入详情页。那么传值的话核心代码如下:
图一
图二

//位于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来加载相应地区的工作。
图三
所以,我们要在用户在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即可。

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

2 1
原创粉丝点击