安卓成长记(六)

安卓成长记

第四章了
activty也有自己的子类。有的业务场景可以继承activity的子类。

activity的子类有:ListActivity,LaunchActivity等,但是常用的也就这俩吧。

你知道人家一般怎么说嘛?
可以使用ArrayAdapter,可以使用SimpleAdapter,当然也可以使用扩展的BaseAdapter。那就说明其实SimpleAdapter一般不扩展,自己定制的话一般是使用BaseAdapter的。

下面的这个LuncherActivity还有点儿看头,别的快不看了,没意思。

package org.crazyit.app;

import android.app.Activity;
import android.app.LauncherActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;


public class MainActivity extends LauncherActivity
{
    //定义两个Activity的名称
    String[] names = {"设置程序参数" ,  "查看星际兵种"};
    //定义两个Activity对应的实现类
    //这里这个很有意思,是定了一个数组,安装要启动的界面。
    //因为要启动的界面是.class后缀的么。
    Class<?>[] clazzs = {PreferenceActivityTest.class
            , ExpandableListActivityTest.class};
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        //这个Adapter也没什么的新奇的,就是一个ArrayAdapter
        //还是一样的配方
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1 , names);
        // 设置该窗口显示的列表所需的Adapter
        setListAdapter(adapter);
    }
    //根据列表项返回指定Activity对应的Intent
    //这个还是初次见
    //下面这个回调函数是LuncherActivity的重要的函数
    //它是根据不同的位置(其实是列表项)启动不同的Intent
    @Override
    public Intent intentForPosition(int position)
    {
        return new Intent(MainActivity.this , clazzs[position]);
    }
}

其实也so easy对不对

我总觉得Activity并没有那么强的归属性。每一个Activity都可以指定IntentFilter的属性用来表示这个Activity可以响应的Intent。那别的程序都可以通过Intent去启动这个Activity啊。

你以前的编程中,有没有注意到,新打开一个Activity之后,要不要把旧的Activity关闭掉呢?就是Activity要关闭掉自身?
比如这样:

close.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                // 获取启动当前Activity的上一个Intent
                Intent intent = new Intent(SecondActivity.this,
                        MainActivity.class);
                // 启动intent对应的Activity
                startActivity(intent);
                // 结束当前Activity
                //在startActivity()之后,要不要关闭掉本身?
                //这是个值得考虑的问题。不关闭掉本身的话,
                //按了返回键,那是回到之前的Activity吧?
                //因为当前的Activity栈里面没有东西了呀!
                //当返回前边Activity的时候,另一个重要的东西就浮现出来了:
                //那就是启动方式。
                //最好是那种不论怎么进入,都是栈里每一个Activity只有一个实例的最好。
                finish();
            }
        });

activity之间的数据传输

其实intent只是“意图”,通俗的讲它只是一个信封,他不携带数据,真正携带数据的是Bundle。只是Bundle是信纸,被Intent携带而已。

下面来看几个Intent的方法:

来自文档
 Bundle getExtras() 
          Retrieves a map of extended data from the intent.
          这里的返回值是一个Bundle,
          用于将Intent里面的内容拿出来
 Intent putExtras(Bundle extras) 
          Add a set of extended data to the intent.  
          这里的参数是Bundle,
          是将一个Bundle放到Intent里面。

注意上面两个方法是用于将budle放到intent里和将intent里面的Bundle拿出来。

下面intent提供了两个“智能”的方法:
不不不,其实是一堆……
Intent putExtra(String name, byte value) 
          Add extended data to the intent. 
 Intent putExtra(String name, byte[] value) 
          Add extended data to the intent. 
 Intent putExtra(String name, char value) 
          Add extended data to the intent. 
 Intent putExtra(String name, char[] value) 
          Add extended data to the intent. 



 short getShortExtra(String name, short defaultValue) 
          Retrieve extended data from the intent. 
 String getStringArrayExtra(String name) 
          Retrieve extended data from the intent. 
 long getLongExtra(String name, long defaultValue) 
          Retrieve extended data from the intent. 
上面的都是Intent的方法,用于将数据“直接”放入Intent中。

用的是putExtra(String name,XXX value)方法放进去的
那就用getXXXExtra(String name)方法取出来。
putXxxExtra(String name,XXX value)的时候,注意里面是键值对。

之所以说是“智能”,其实一点儿也不智能。因为这些方法虽然是Intent提供的,但是本质上也还是利用Bundle去传递数据,只是Intent隐藏了这一层。
Bundle的几种方法:

char getChar(String key) 
          Returns the value associated with the given key, or false if no mapping of the desired type exists for the given key. 

char[] getCharArray(String key) 
          Returns the value associated with the given key, or null if no mapping of the desired type exists for the given key or a null value is explicitly associated with the key. 

 float getFloat(String key) 
          Returns the value associated with the given key, or 0.0f if no mapping of the desired type exists for the given key. 


void putByte(String key, byte value) 
          Inserts a byte value into the mapping of this Bundle, replacing any existing value for the given key. 


void putDouble(String key, double value) 
          Inserts a double value into the mapping of this Bundle, replacing any existing value for the given key. 


 void putLong(String key, long value) 
          Inserts a long value into the mapping of this Bundle, replacing any existing value for the given key. 


也就是,putXXX(string name,XXX value)
参数和上面Intent的是一样的,只是没有了那个Extra。
getXXX(String key)里面只有一个参数,键值对的key。


在Bundle里面是key-value的。

不过Bundle有一个大招:

void putSerializable(String key, Serializable value) 
          Inserts a Serializable value into the mapping of this Bundle, replacing any existing value for the given key. 

 Serializable getSerializable(String key) 
          Returns the value associated with the given key, or null if no mapping of the desired type exists for the given key or a null value is explicitly associated with the key. 

是放一个可序列化的对象。这个就是很重要的了,比如放一个对象之类的,
有时候不同的Activity可传递业务Bean,就是这样传递的。

这样的做法,Person这个业务类被称为DTO对象,是Data To Object的意思么?好像是的。

注意一个重要的方法:

getIntent()
如果是在新启动的Activity中,那这个方法用于获取前面传过来的Intent。

主界面的代码:

public class MainActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button bn = (Button) findViewById(R.id.bn);
        bn.setOnClickListener(new OnClickListener()
        {
            public void onClick(View v)
            {
                EditText name = (EditText)findViewById(R.id.name);
                EditText passwd = (EditText)findViewById(R.id.passwd);
                RadioButton male = (RadioButton) findViewById(R.id.male);
                String gender = male.isChecked() ? "男 " : "女";
                //这个就是构造那个业务对象
                Person p = new Person(name.getText().toString(), passwd
                        .getText().toString(), gender);
                // 创建一个Bundle对象
                //直接创建一个Bundle对象之后PutSerializable()就行了
                //将那个数据对象放进Bundle里面
                Bundle data = new Bundle();
                data.putSerializable("person", p);
                // 创建一个Intent
                Intent intent = new Intent(MainActivity.this,
                        ResultActivity.class);
                //Intent把Bundle带上
                intent.putExtras(data);
                // 启动intent对应的Activity
                startActivity(intent);
            }
        });
    }
}

咱一会儿说那个DTO对象,先说第二个Activvity

public class ResultActivity extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.result);
        TextView name = (TextView) findViewById(R.id.name);
        TextView passwd = (TextView) findViewById(R.id.passwd);
        TextView gender = (TextView) findViewById(R.id.gender);
        // 获取启动该Activity的Intent

        //看清楚了啊都,就这个方法,获取到前面传过来的Intent。
        Intent intent = getIntent();
        //这里其实是用到了“智能化”的Intent。
        //因为person其实是在Bundle中的,但是现在直接intent.getSerializableExtra()了
        //注意这个Extra就很重要,代表这个是Intent干了Bundle的活。
        //如果你这样,Bundle bundle=intent.getExtras(),Person p=bundle.getSerializable()也是一样的道理。
        //intent的方法是有一点“智能化”的。
        //这种智能无非是通过重载,说的有多高级似的。
        Person p = (Person) intent.getSerializableExtra("person");
        name.setText("您的用户名为:" + p.getName());
        passwd.setText("您的密码为:" + p.getPasswd());
        gender.setText("您的性别为:" + p.getGender());
    }
}

这个domain很重要,意思他就是携带数据的业务类
里面都是应该有的成分和get set方法。

package org.crazyit.domain;

import java.io.Serializable;

public class Person implements Serializable{
    private Integer id;
    private String name;
    private String passwd;
    private String gender;

    public Person(String name, String passwd, String gender) {
        this.name = name;
        this.passwd = passwd;
        this.gender = gender;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPasswd() {
        return passwd;
    }

    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

回传信息

下面介绍,第二个Activity返回信息。

void startActivityForResult(Intent intent, int requestCode)
Launch an activity for which you would like a result when it finished.

这个是Activity的方法,无非是要加一个requestCode。
不过另外还要回调(实现,重写,一个意思)一个方法:

protected void onActivityResult(int requestCode, int resultCode, Intent data)

这个是系统回调的,当有结果返回回来,触发。
(于是这就是第二种事件处理的方法。)

被启动的Activity还要有setResult()去处理结果。

public class MainActivity extends Activity
{
    Button bn;
    EditText city;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取界面上的组件
        bn = (Button) findViewById(R.id.bn);
        city = (EditText) findViewById(R.id.city);
        // 为按钮绑定事件监听器
        bn.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View source)
            {
                // 创建需要对应于目标Activity的Intent
                Intent intent = new Intent(MainActivity.this,
                        SelectCityActivity.class);
                // 启动指定Activity并等待返回的结果,其中0是请求码,用于标识该请求
                startActivityForResult(intent, 0);
            }
        });
    }
    // 重写该方法,该方法以回调的方式来获取指定Activity返回的结果
    @Override
    public void onActivityResult(int requestCode
            , int resultCode, Intent intent)
    {
        // 当requestCode、resultCode同时为0时,也就是处理特定的结果
        //这个判定其实很重要。那个界面打开的,
        //那个界面返回来的数据其实都要判断。
        if (requestCode == 0 && resultCode == 0)
        {
            // 取出Intent里的Extras数据
            Bundle data = intent.getExtras();
            // 取出Bundle中的数据
            String resultCity = data.getString("city");
            // 修改city文本框的内容
            city.setText(resultCity);
        }
    }
}

被启动的Activity:

//这个无非是可扩展列表框的监听事件
getExpandableListView().setOnChildClickListener(
            new OnChildClickListener()
            {
                @Override
                public boolean onChildClick(ExpandableListView parent,
                    View source, int groupPosition, int childPosition,
                                            long id)
                {
                    // 获取启动该Activity之前的Activity对应的Intent
                    //先通过getIntent()获取到启动它的Activity传过来的Intent
                    Intent intent = getIntent();
                    intent.putExtra("city",
                            cities[groupPosition][childPosition]);
                    // 设置该SelectCityActivity的结果码,并设置结束之后退回的Activity
                    //直接使用setReslt()也是可以的吧?
                    SelectCityActivity.this.setResult(0, intent);
                    // 结束SelectCityActivity。
                    SelectCityActivity.this.finish();
                    return false;
                }
            });

activity的几种加载模式

  • standard模式
  • single Top模式
  • single task模式
  • singleInstance模式

standard模式:
这种模式,每次都会为新启动的Activity创建一个新的实例,将新创建的实例加到task栈中
如果写一个程序不断启动自身的话,那启动几次,栈中就会有几个实例,
退出的话也挺麻烦,一个一个退。

其实你在按返回键的时候就是在删除栈顶的Activity。

single Top方式:
-已经位于栈顶的Activity不会被创建新的实例
-没有位于栈顶的元素会被创建出一个实例,也就是说能出现activity1,activity2,activity1的场景

single Task模式:
-只有一个task栈。
-一个task栈里面一个Activity只有一个实例如果以前有的话,将这个Activity移到栈顶去。
-注意不是移到栈顶,而是将这个Activity上面的Activity全部移出去。

singleInstence
-这种是维护多个Task的。
-每一个task里面有一个Activity
-那个Activity被启动,那个Activity对应的task转到前台
-保证了每个Activity只有一个实例,而且不像singleTask会将别的删除了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值