天天看點

Activity的基礎知識

前言

長風破浪會有時,直挂雲帆濟滄海。

關于Activity的啟動和關閉

一個Android應用程式通常都包含多個Activity,但隻有一個Activity會作為程式的入口——當該Android應用運作時将會自動啟動并執行該Activity。至于應用中的其他Activity,通常都由入口Activity啟動,或由入口Activity啟動的Activity啟動。

Activity啟動其他Activity有如下兩個方法。

  • startActivity(Intent intent):啟動其他Activity。
  • startActivityForResult(Intent intent,int requestCode):以指定的請求碼(requestCode)啟動Activity,而且程式将會擷取新啟動的Activity傳回的結果(通過重寫OnActivityResult(...)方法)。

上面兩個方法都用到了Intent參數,Intent是Android應用裡各元件之間同通信的重要方式,一個Activity通過Intent來表達自己“意圖”——想要啟動哪個元件,被啟動的元件既可是Activity元件,也可是Service元件。

Android為關閉Activity準備了如下兩個方法。

  • finish():結束目前Activity。
  • finishActivity(int requestCode):結束以startActivityForResult(Intent intent,int requestCode)方法啟動的Activity。

代碼示例

FirstActivity.java
public class FirstActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        Button bt = (Button) findViewById(R.id.bt);
        bt.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //建立需要啟動的Activity對應的Intent
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                //啟動intent對應的Activity
                startActivity(intent);
            }
        });
    }
}

           
SecondActivity.java
public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.seconde_layout);
        Button back = (Button) findViewById(R.id.back);
        Button back_finish = (Button) findViewById(R.id.back_finish);

        back.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                //建立需要啟動的Activity對應的Intent
                Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
                //啟動intent對應的Activity
                startActivity(intent);
            }
        });

        back_finish.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //建立需要啟動的Activity對應的Intent
                Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
                //啟動intent對應的Activity
                startActivity(intent);
                //結束目前Activity
                finish();
            }
        });
    }
}
           

提示

上述程式的布局檔案就隻包含簡單的按鈕來實作跳轉,第二個Activity唯一的差別就是finish()方法,它表明該Activity會結束自己。

使用Bundle在Activity之間交換資料

當一個Activity啟動另一個Activity時,常常會有一些資料需要傳過去。這時Intent就相當于一個“信使”,我們将需要傳送的資料存入Intent中即可。、

Intent提供了多個方法來“攜帶”額外的資料,如下所示。

  • putExtras(Bundle data):向Intent中放入需要“攜帶”的資料包。
  • Bundle getExtras():取出Intent中所“攜帶”的資料包。
  • putExtra(String name,Xxx value):向Intent中按key-value對的形式存入資料。
  • getXxxExtra(String name):從Intent中按key取出指定類型的資料。

上述方法中的Bundle就是一個簡單的資料攜帶包,該Bundle對象包含了多個方法來存入資料。

  • putXxx(String key, Xxx value):向Bundle中放入Int、Long等各種類型的資料。
  • putSerializable(String key, Serializable data):向Bundle中放入一個可序列化的對象。
  • getXxx(String key):從Bundle中取出Int、Long等各種類型的資料。
  • getSerializable(String key):從Bundle中取出一個可序列化的對象。

下面我通過一個執行個體來介紹Activity之間如何通過Bundle交換資料。

本程式包含兩個Activity,其中第一個Activity用于收集使用者的輸入資訊,當使用者單擊該Activity的“注冊”按鈕時,應用進入第二個Activity,第二個Activity将會擷取第一個Activity中的資料。

public class FirstActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);

        Button bn = (Button) findViewById(R.id.bn);
        bn.setOnClickListener(new OnClickListener() {

            @Override
            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();
                p.setName(name.getText().toString());
                p.setPasswd(passwd.getText().toString());
                p.setGender(gender);

                //建立一個Bundle對象
                Bundle data = new Bundle();
                data.putSerializable("person", p);
                //建立一個Intent
                Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                intent.putExtras(data);
                //啟動intent對應的Activity
                startActivity(intent);
            }
        });
    }
}

           
first_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="請輸入您的注冊資訊"
        android:textSize="20sp" />

    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="使用者名:"
            android:textSize="16sp" />

        <EditText
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="請填寫想注冊的賬号"
            android:selectAllOnFocus="true" />
    </TableRow>

    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="密碼:"
            android:textSize="16sp" />

        <EditText
            android:id="@+id/passwd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:password="true"
            android:selectAllOnFocus="true" />
    </TableRow>

    <TableRow>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="性别:"
            android:textSize="16sp" />
        <RadioGroup
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <RadioButton
                android:id="@+id/male"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="男"
                android:textSize="16sp"
                />
            <RadioButton
                android:id="@+id/female"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="女"
                android:textSize="16sp"
                />
        </RadioGroup>
    </TableRow>
    <Button
        android:id="@+id/bn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注冊"
        android:textSize="16sp"
        />
</TableLayout>
           
public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.seconde_layout);

        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 = getIntent();
        //直接通過Intent取出它所攜帶的Bundle資料包中的資料
        Person p = (Person) intent.getSerializableExtra("person");
        name.setText("您的使用者名為:" + p.getName());
        passwd.setText("您的密碼為:" + p.getPasswd());
        gender.setText("您的性别為:" + p.getGender());
    }
}
           
seconde_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        />
    <TextView
        android:id="@+id/passwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        />
    <TextView
        android:id="@+id/gender"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        />

</LinearLayout>

           

效果

[圖檔上傳失敗...(image-e4b6ea-1514096470518)]

[圖檔上傳失敗...(image-2ca6b1-1514096470519)]

需要傳送資料如果是對象,這個對象應該實作Serializable接口。

啟動其他Activity并傳回結果

前面已經提到,Activity還提供了一個startActivityForResult(Intent intent,int requestCode)方法來啟動其他Activity。該方法用于啟動指定Activity,而且期望擷取指定Activity傳回的結果。這種情況很常見,例如應用程式第一個界面需要使用者進行選擇,但需要選擇的清單資料比較複雜,必須啟動另一個Activity讓使用者選擇。當使用者在第二個Activity中選擇完成後,程式傳回第一個Actvity,第一個Activity必須能擷取并顯示使用者在第二個Activity中選擇的結果。在這種應用場景下,也通過Bundle進行資料交換的。

為了擷取被啟動的Activity所傳回的結果,需要從兩方面着手。

  • 目前Activity需要重寫onActivityResult(int requestCode,int resultCode,Intent intent),當被啟動的Activity傳回結果時,該方法會被觸發,其中requestCode代表請求碼,而resultCode代表Activtiy傳回的結果碼,由開發者自行設定。
  • 被啟動的Activtiy需要調用setResult()方法設定處理結果。

一個Activity中可能包含多個按鈕,并調用多個startActivityForResult()方法來打開多個不同的Activity處理不同的業務,當這些新Activity關閉後,系統将回調前面Activity的onActivityResult(int requestCode,int resultCode,Intent data)方法。為了知道該方法是由哪個請求的結果所觸發的,可利用requestCode請求碼;為了知道傳回的資料來自于哪個新的Activity,可利用resultCode結果碼。

public class FirstActivity extends Activity {

    Button bt;
    EditText city;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);

        bt = (Button) findViewById(R.id.bt);
        city = (EditText) findViewById(R.id.city);

        bt.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                //建立需要對應于目标Activity的Intent
                Intent intent = new Intent(FirstActivity.this, SelectCityActivity.class);
                //啟動指定Activity并等待傳回的結果,其中0是請求碼,用于辨別該請求
                startActivityForResult(intent, 0);
            }
        });
    }

    //重寫該方法,該方法以回調的方式來擷取指定Activity傳回的結果
    @Override
    protected 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);
        }
    }
}
           
SelectCityActivity.java
public class SelectCityActivity extends ExpandableListActivity {

    //定義省份數組
    private String[] provinces = new String[]
    {"廣西","廣東","湖南","雲南"};

    private String[][] cities = new String[][]
    {
        {"桂林","柳州","南甯","北海"},
        {"廣州","深圳","珠海","中山"},
        {"長沙","嶽陽","衡陽","株洲"},
        {"昆明","玉溪","大理","麗江"}
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ExpandableListAdapter adapter = new BaseExpandableListAdapter() {

            @Override
            public boolean isChildSelectable(int groupPosition, int childPosition) {
                return true;
            }

            @Override
            public boolean hasStableIds() {
                return true;
            }

            private TextView getTextView() {
                AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 64);
                TextView textView = new TextView(SelectCityActivity.this);
                textView.setLayoutParams(lp);
                textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT);
                textView.setPadding(36, 0, 0, 0);
                textView.setTextSize(20);
                return textView;
            }

            @Override
            public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

                LinearLayout ll = new LinearLayout(SelectCityActivity.this);
                ll.setOrientation(LinearLayout.HORIZONTAL);
                ImageView logo = new ImageView(SelectCityActivity.this);
                logo.setImageResource(R.drawable.ic_launcher);
                ll.addView(logo);
                TextView textView = getTextView();
                textView.setText(getGroup(groupPosition).toString());
                ll.addView(textView);
                return ll;
            }

            @Override
            public long getGroupId(int groupPosition) {
                return groupPosition;
            }

            @Override
            public int getGroupCount() {
                return provinces.length;
            }

            @Override
            public Object getGroup(int groupPosition) {
                return provinces[groupPosition];
            }

            @Override
            public int getChildrenCount(int groupPosition) {
                return cities[groupPosition].length;
            }

            @Override
            public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
                    ViewGroup parent) {
                TextView textView = getTextView();
                textView.setText(getChild(groupPosition, childPosition).toString());
                return textView;
            }

            @Override
            public long getChildId(int groupPosition, int childPosition) {
                // TODO Auto-generated method stub
                return childPosition;
            }

            @Override
            public Object getChild(int groupPosition, int childPosition) {
                // TODO Auto-generated method stub
                return cities[groupPosition][childPosition];
            }
        };

        setListAdapter(adapter);
        //為清單項設定監聽
        getExpandableListView().setOnChildClickListener(new OnChildClickListener() {

            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {

                //擷取啟動該Activity之前的Activity對應的Intent
                Intent intent = getIntent();
                intent.putExtra("city", cities[groupPosition][childPosition]);
                //設定該SelectCityActivity的結果碼,并設定結束之後退回的Activity
                SelectCityActivity.this.setResult(0, intent);
                //結束SelectCityActivity
                SelectCityActivity.this.finish();
                return false;
            }
        });
    }
}
           

Activity的基礎知識

Screenshot_20171101-145622.png

Activity的基礎知識

Screenshot_20171101-145711.png

Activity的基礎知識

Screenshot_20171101-145743.png

别忘記每建立一個新的Activity,都要去清單檔案裡注冊這個Activity。

繼續閱讀