android基礎--四大組件之Activity

android四大組件之Activity

1. 添加新Activity的步驟
    1) 定義類繼承Activity
    2) 在AndroidManifest.xml文件中聲明Activity信息。
        操作系統要想找到activity,就必須在清單文件中進行配置。最簡單的配置如下:
        <activity android:name="com.itheima40.activitydemo.SecondActivity" />
        ---<activity>元素配置在<application>元素裏面,<activity>和<application>都有android:icon和android:label屬性,界面上快捷圖標和名稱都是activity的icon和label,而不是application中的icon和label,application的圖標和名稱在系統設置->應用中可以看到。如果activity沒有設置其android:icon或android:label,默認使用application的這2個屬性。

<application
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/application_name"
 android:theme="@style/AppTheme" >
 <activity
  android:name="com.itheima40.activitydemo.MainActivity"
  android:label="@string/app_name" >
  <intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
 </activity>
 
 <activity android:name="com.itheima40.activitydemo.ui.SecondActivity" >
  <intent-filter>
   <action android:name="android.intent.action.MAIN" />               
   <category android:name="android.intent.category.LAUNCHER" />             
  </intent-filter>
 </activity>
</application>
----採用這種配置的應用,部署後,在桌面上會有2個圖標,分別是不同activity的入口。

    3) 在類中實現onCreate方法, 設置佈局。
        onCreate()方法用來實現Activity的一些初始化工作。

2. 多個activity頁面之間的跳轉

    activity跳轉時要用到android.content.Intent類,Intent描述一個頁面信息,同時也是一個數據載體。

    頁面之間有2種跳轉方式:顯式跳轉和隱式跳轉。

    顯式跳轉
    在可以引用到那個類, 並且可以引用到那個類的字節碼時. 一般用於在自己程序的內部. 顯示跳轉不可以跳轉到其他程序的頁面中。
    顯式跳轉的幾種形式:
    * Intent setClass(Context packageContext, Class<?> cls),cls類名只寫單個類名,不用寫完全類名。
    * Intent setClassName(Context packageContext, String className),className是完整類名。
    * Intent setClassName(String packageName, String className),這裏的packageName是應用的包名,不一定是Activity所在的包。
    * 在Intent構造方法中指定要跳轉的activity。
      Intent(Context packageContext, Class<?> cls),這裏的cls中的類名也不需要是完整包名。

    可用顯式跳轉激活系統的一個應用程序的界面。
    在模擬器中打開一個系統應用,查看logCat中的打印。
    如打開圖庫時,logcat中打印如下:
09-10 11:28:42.905: I/ActivityManager(215): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.gallery/com.android.camera.GalleryPicker u=0} from pid 386

其中,cmp=com.android.gallery/com.android.camera.GalleryPicker中com.android.gallery就是應用的包名,com.android.camera.GalleryPicker就是Activity的類名。

    再比如,瀏覽器應用
09-10 11:38:20.215: I/ActivityManager(215): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.browser/.BrowserActivity u=0} from pid 386
    這裏,com.android.browser/.BrowserActivity,Activity的包名省略,表示和應用包名一樣。
    注:不同版本的android模擬器中,同一個應用的包名和類名可能不同,這種顯式方式激活系統應用就不一定能用了,耦合性較高。
    同一個版本的android模擬器中,也可能有同一功能的不同應用,用戶想要的是對一個動作有頁面去響應,而並不特指哪個頁面,這時用包名+類名的方式跳轉就不太合適。

   隱式跳轉
   可以在當前程序跳轉到另一個程序的頁面, 而且不需要引用那個類.,必須得知道那個界面的動作和信息。

<intent-filter>
 <action android:name="com.cx.second" />
 <category android:name="android.intent.category.DEFAULT" /> 
 // 指定傳遞的數據是以: money開頭
 <data android:scheme="money"/> 
 // 指定傳遞過去的類型, 用於區分當前是什麼操作.
 <data android:mimeType="com.itheima40/mbx" /> 
</intent-filter>
----<intent-filter>的作用相當於window系統中的文件關聯(比如什麼文件用什麼程序打開,是寫在註冊表裏的),定義一個activity的一些動作。
----<category>表示動作的附加信息,提供一些執行的環境信息參數。
      如果沒有附加信息,需要加如下配置設置category爲DEFAULT,不加的話隱式跳轉匹配時可能會出錯:
      <category android:name="android.intent.category.DEFAULT"/>
     編寫代碼時可以不寫intent.addCategory("android.intent.category.DEFAULT"),因爲每個intent默認就有這個category,但建議最好加上。
----下面這種方式定義action時,當前應用程序會在桌面應用中產生快捷圖標。
      <intent-filter>
       <action android:name="android.intent.action.MAIN" />              
       <category android:name="android.intent.category.LAUNCHER">
      </intent-filter>

   在應用中打開瀏覽器頁面
   android系統源碼/package/app/bowser應用清單文件中瀏覽器activity的設置如下:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="http" />
  <data android:scheme="https" />
  <data android:scheme="about" />
  <data android:scheme="javascript" />
 </intent-filter>
  編程代碼如下:
Intent intent = new Intent();
 intent.setAction("android.intent.action.VIEW");
 intent.addCategory("android.intent.category.BROWSABLE");//DEFAULT的category不用添加。
 Uri uri = Uri.parse("http://www.itheima.com");
 intent.setData(uri);
 startActivity(intent);  
   在應用中打開系統短信發送的頁面
   android系統源碼/package/app/Mms應用清單文件中短信發送器activity的設置如下:
<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <action android:name="android.intent.action.SENDTO" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="sms" />
  <data android:scheme="smsto" />
 </intent-filter>
----一個activity中可以有多個<intent-filter>,一個<intent-filter>中也可以有多個action,編程時只要符合其中的一個即可。
   編程代碼如下:
 Intent intent = new Intent();
 intent.setAction("android.intent.action.VIEW");
 intent.addCategory("android.intent.category.BROWSABLE");
 Uri uri = Uri.parse("sms:5556");
 intent.setData(uri);
 // 使用intent傳遞數據
 intent.putExtra("sms_body", "hhhhhhhhh!!!");//sms_body是android系統寫死的,系統中短信發送器接收sms_body這個key值對應的數據作爲其短信內容。
 startActivity(intent);
   打開圖庫Activity

   圖庫源碼:

<activity android:name="com.android.camera.ImageGallery"
                android:label="@string/gallery_label"
                android:configChanges="orientation|keyboardHidden"
                android:icon="@drawable/ic_launcher_gallery">
            .......
            <intent-filter>
                <action android:name="android.intent.action.PICK" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="image/*" />
                <data android:mimeType="video/*" />
            </intent-filter>
          .......
           
</activity>
   編程代碼:
Intent intent=new Intent();
intet.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityFroResult(intent,0);

  隱式意圖執行原理:
   1. 查詢系統裏面的所有的activity,看看是不是有滿足條件的activity:需要進行三個匹配,一個是action,一個是category,一個是data。
   2. 如果有,判斷有多少個,只有1個時直接啓動,如果有多個,彈出列表對話框讓用戶選擇。
   3. 如果沒有,應用程序會異常終止,activity not found exception。

同一個應用程序裏面,自己激活自己的東西,推薦使用顯式意圖,效率高。
不同的應用程序裏面,激活別人的應用,或者是讓自己的某一個界面希望被別人激活,推薦使用隱匿意圖。

3. Activity間傳遞數據

    發送數據
    使用intent進行activity之間跳轉時,可以傳遞數據,使用的方法是intent.setData()或者intent.putExtra()。
    在一個activity的<intent-filter>元素中添加<data>標籤,指定數據的規範/約束,如
<data android:scheme="sms" />,scheme可理解爲表示數據的前綴。
    如果在一個activity中設置了<data>元素,那麼其它應用/本應用其它activity在調用startActivity(intent)跳轉到這個activity前,必須設置這個intent的data,使用方法setData(uri)方法傳遞數據。

    <data>元素還有一個屬性mimeType,用來指定數據的類型:
    <data android:mimeType="com.itheima40/mbx" /> //mimeType值可隨意。
    同樣,如果設置了mimeType屬性,在編程時也必須用setType指定傳遞的數據的類型,如setType("com.itheima40/mbx")。

     setData()和setType()方法是互斥的,2個方法的實現代碼中會把對方數據設置爲空,所以2個方法不能一塊使用,如果要同時指定數據和數據類型,應該使用setDataAndType(Uri,String)這個方法。
     setData只能傳遞String字符串數據。

     跳轉頁面時指定的數據和類型,可以在跳轉到的頁面中使用getIntent(),getData()獲取。

    使用putExtra()/getXXXExtra()等方法也可以傳遞數據。
    這種方式可傳遞的數據類型: 八大基本類型和數組, String和String[],ArrayList<String>, Bundle數據捆, 實現了Serializable序列化接口的對象(javabean)。

    這裏列舉Intent幾個相關方法,具體使用請求查詢API。
    Intent相關API
    Uri getData(),Retrieve data this intent is operating on. ---uri.toString(),可顯示傳遞的數據。
    String getType(),Retrieve any explicit MIME type included in the intent.
    Intent setData(Uri data),Set the data this intent is operating on. 
    Intent setType(String type),Set an explicit MIME data type. 
    public Intent setDataAndType(Uri data,String type),同時設置數據和數據類型。
    Intent putExtra(String name, String[] value) 
    String[] getStringArrayExtra(String name) 
    Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value)
    ArrayList<Integer> getIntegerArrayListExtra(String name)
    Intent putExtra(String name, Bundle value) 
    Bundle getBundleExtra(String name) 
    注:key都是String。
           Bundle,數據捆,類似javabean,可往裏面存入數據或取出數據,方法如下:
           void putDoubleArray(String key, double[] value) 
           int[] getIntArray(String key) 
           int getInt(String key)

一個頁面跳轉到另一個頁面時,如果傳遞的數據過多,可能會導致跳轉中間界面有一段黑屏。不宜傳送太多數據。

   回傳數據
   操作步驟:
   1. 使用startActivityForResult方法開啓新的頁面。
   2. 在被開啓的新的頁面裏, 調用setResult方法設置回傳的數據。設置完後不會立刻傳遞到前一個頁面, 而是等待新的頁面關閉後,纔回傳。
   3. 回傳給開啓Activity的onActivityResult。
   相關api:
    public void startActivityForResult(Intent intent,int requestCode),要以這種方式開啓新的activity,還可以接收新activity傳回的參數。
    protected void onActivityResult(int requestCode,int resultCode,Intent data),新開啓的activity頁面返回時調用的方法。
    public final void setResult(int resultCode,Intent data),新的activity中向打開它的頁面返回數據的方法。
    void finish(),activity的方法,關閉當前的activity,然後傳遞數據給調用者,調用者就會執行onActivityResult方法。

    requestCode請求碼的作用
    如果同一個界面上有2個或2個以上地方需要開始新的Activity(開啓的activity可以一樣)時,可以在startActivityForResult(intent,requestCode)方法中設置不同的請求碼;startActivityForResult中的請求碼在新的activity結束後會傳遞給onActivityResult函數(一個界面只有一個),在該方法中可以判斷請求碼,根據不同的請求碼執行不同的操作。

    resultCode結果碼的作用
    可以指定返回數據的不同類型,新的activity中setResult設置的resultCode值也會傳給onActivityResult方法,可以該方法依據不同的返回值類型進行不同的數據處理操作。

    短信羣發代碼示例:

    主頁面MainActivity.java:

package com.cx.messagesend;

/**
 * 已實現功能:通過SelectContactActivity選擇聯繫人並返回所選聯繫人,能給這些選擇的人發短信。
 *            實現了Parcelable傳遞數據,parcelable是數據包裝接口,裏面可以自定義實現數據的寫入和讀取方式 。
 * 未實現功能:SelectContactActivity未設置保存功能,界面返回後之前選擇的聯繫人都沒了;
 *            不能對聯繫人輸入框進行手動更新,手動添加的聯繫人不會發短信(後續考慮只返回聯繫人姓名,返回數據寫入輸入框,可以手動更新輸入框,讀聯繫人時根據name找phoneNum,找不到的直接原樣給這個字符串發短信。)
 */

import java.util.ArrayList;
import com.cx.domain.ContactInfo;
import android.os.Bundle;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.telephony.SmsManager;
import android.view.View;

import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private ArrayList<ContactInfo> checkedContactsList;
	private TextView etPhoneNum;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ImageButton mBtnSend;
		mBtnSend =  (ImageButton) findViewById(R.id.btn_send);
		etPhoneNum =(TextView) findViewById(R.id.et_telnum);
		
	}
	public void selectContact(View v){
		
		Intent intent=new Intent(this,SelectContactActivity.class);
		startActivityForResult(intent, 0);
	}
		
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		checkedContactsList = data.getParcelableArrayListExtra("checkedcontacts");
		
		StringBuilder sb=new StringBuilder();
		for(ContactInfo contactInfo:checkedContactsList){
			sb.append(contactInfo.getName()+";");			
		}
		etPhoneNum.setText(sb.toString());
		
	}
	public void send(View v) {
		
			EditText mEditContent=(EditText)findViewById(R.id.et_content);

			String strEditContent= mEditContent.getText().toString().trim();
			
			SmsManager smsManager = SmsManager.getDefault();
			PendingIntent sentIntent = PendingIntent.getBroadcast(MainActivity.this, 0, new Intent(), 0);
			for(ContactInfo contactInfo:checkedContactsList){
				smsManager.sendTextMessage(contactInfo.getPhoneNum(), null, strEditContent, sentIntent, null);
			}			
			Toast.makeText(MainActivity.this,"短信發送完成", Toast.LENGTH_LONG).show();
	    	
	}				    	
}

     選擇聯繫人頁面SelectContactActivity.java:

package com.cx.messagesend;

import java.util.ArrayList;
import java.util.List;
import com.cx.domain.ContactInfo;
import com.cx.service.ContactInfoService;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

public class SelectContactActivity extends Activity {

	ListView lvContacts;
	List<ContactInfo> contactsList;
	List<ContactInfo> checkedContactsList;
	ArrayList<Integer> checkList;
	private ContactsAdapter cAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_contacts);
		contactsList = ContactInfoService.getContactInfo(this);
		lvContacts = (ListView) findViewById(R.id.lv_contacts);

		cAdapter = new ContactsAdapter();
		lvContacts.setAdapter(cAdapter);

	}

	public void submit(View v) {
		super.onDestroy();
		checkList = new ArrayList<Integer>();
		checkedContactsList = new ArrayList<ContactInfo>();
		if (cAdapter.mChecked != null) {
			for (int i = 0; i < cAdapter.mChecked.size(); i++) {
				if (cAdapter.mChecked.get(i)) {
					checkList.add(i);
					checkedContactsList.add(contactsList.get(i));
				}
			}
		}

		Intent intent = new Intent();
		intent.putParcelableArrayListExtra("checkedcontacts",
				(ArrayList<? extends Parcelable>) checkedContactsList);
		System.out.println("In second...."
				+ (ArrayList<? extends Parcelable>) checkedContactsList);
		setResult(0, intent);
		finish();
	}

	public void cancel(View v) {

	}

	public class ContactsAdapter extends BaseAdapter {

		List<Boolean> mChecked;

		public ContactsAdapter() {
			mChecked = new ArrayList<Boolean>();
			for (int i = 0; i < contactsList.size(); i++)
				mChecked.add(false);
		}

		@Override
		public int getCount() {
			return contactsList.size();
		}

		@Override
		public Object getItem(int position) {
			return null;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(final int position, View convertView,
				ViewGroup parent) {

			ContactInfo cinfo = contactsList.get(position);

			if (convertView == null) {
				// 佈局填充器, 打氣筒, 功能: 把佈局文件, 轉換成一個View對象
				LayoutInflater inflater = LayoutInflater
						.from(SelectContactActivity.this);
				convertView = inflater.inflate(R.layout.contact_item, null);
			}

			TextView tvName = (TextView) convertView.findViewById(R.id.tv_name);
			TextView tvNum = (TextView) convertView.findViewById(R.id.tv_num);

			CheckBox cbSelect = (CheckBox) convertView.findViewById(R.id.cb);
			cbSelect.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					CheckBox cb = (CheckBox) v;
					mChecked.set(position, cb.isChecked());
				}
			});

			tvName.setText(cinfo.getName());
			tvNum.setText(cinfo.getPhoneNum());

			return convertView;
		}

	}

}
     獲取聯繫人服務ContactInfoService.java

package com.cx.service;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;

import com.cx.domain.ContactInfo;

public class ContactInfoService {
	
	public static List<ContactInfo> getContactInfo(Context context){
		
		List<ContactInfo> contactsList=new ArrayList<ContactInfo>();
		ContentResolver resolver=context.getContentResolver();
		Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");
		Uri dataUri=Uri.parse("content://com.android.contacts/data");		
		Cursor cursor=resolver.query(uri, new String[]{"contact_id"}, null, null, null);
		while(cursor.moveToNext()){
			String id=cursor.getString(0);
			if(id!=null){
				Cursor dataCursor =resolver.query(dataUri, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{id}, null);
				ContactInfo contactInfo=new ContactInfo();
				while(dataCursor.moveToNext()){
					String data = dataCursor.getString(0);
					String mimetype=dataCursor.getString(1);
					if( "vnd.android.cursor.item/name".equals(mimetype)){
						contactInfo.setName(data);		               
					}else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
						contactInfo.setPhoneNum(data);
					}
				}
			if(contactInfo.getName()!=null && contactInfo.getPhoneNum()!=null)
			     contactsList.add(contactInfo);
			dataCursor.close();
			}		
		}
		return contactsList;
	}

}
    聯繫人類ContactInfo.java:
package com.cx.domain;

import android.os.Parcel;
import android.os.Parcelable;

public class ContactInfo implements Parcelable {
	String name;
	String phoneNum;

	public ContactInfo() {
		super();
	}

	@Override
	public String toString() {
		return "ContactInfo [name=" + name + ", phoneNum=" + phoneNum + "]";
	}

	public ContactInfo(String name, String phoneNum) {
		super();
		this.name = name;
		this.phoneNum = phoneNum;
	}

	public ContactInfo(Parcel in) {
		name = in.readString();
		phoneNum = in.readString();
	}

	public String getName() {
		return name;
	}

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

	public String getPhoneNum() {
		return phoneNum;
	}

	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(name);
		dest.writeString(phoneNum);
	}

	public static final Parcelable.Creator<ContactInfo> CREATOR = new Parcelable.Creator<ContactInfo>() {
		public ContactInfo createFromParcel(Parcel in) {
			return new ContactInfo(in);
		}

		public ContactInfo[] newArray(int size) {
			return new ContactInfo[size];
		}
	};
}
    佈局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dip"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/et_telnum"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="10"
            android:hint="請輸入或選擇聯繫人"
            android:inputType="phone" />

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:src="@drawable/ic_menu_cc"
            android:onClick="selectContact" />
        
    </LinearLayout>
    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="5dip"
        android:layout_marginLeft="5dip"
        android:orientation="horizontal">
        <EditText
        android:id="@+id/et_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="10"
        android:hint="請輸入短信內容"
        android:inputType="textMultiLine"/><!-- 設置爲多行且不指定有幾行時,默認顯示1行,超過時自動換行 -->

    <ImageButton
        android:id="@+id/btn_send"
        android:onClick="send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/ic_menu_set_as"/>
   </LinearLayout>
</RelativeLayout>
<?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" >
    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="5dip"
        android:hint="取消"
        android:onClick="cancel"
    />
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginRight="5dip"
        android:hint="確定"
        android:onClick="submit"
    />
    </RelativeLayout>
    <ListView 
        android:id="@+id/lv_contacts"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    ></ListView>   

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_marginTop="5dip"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dip"
        android:layout_weight="5"
        
        android:orientation="vertical" >

     <TextView 
      android:id="@+id/tv_name"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textSize="15sp" 
     android:text="sdfd"/>  
      
     <TextView 
     android:id="@+id/tv_num"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" 
     android:textSize="12sp" 
     android:text="xggggggg"/> 
     
    </LinearLayout>
<!-- checkbox會自動搶佔整個listview條目的焦點-->
    <CheckBox
        android:id="@+id/cb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="0.45" /> 
    
</LinearLayout>
     清單文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cx.messagesend04"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.SEND_SMS"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.cx.messagesend04.MainActivity"
            android:theme="@android:style/Theme.Light.NoTitleBar"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.cx.messagesend04.SelectContactActivity"
            android:theme="@android:style/Theme.Light.NoTitleBar"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.SelectContact" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

</manifest>

4. Activity生命週期
    Activity生命週期
    startActivity開啓一個Activity時,生命週期的過程是: onCreate -> onStart(可見, 但不可交互) -> onResume(可見, 可交互)。
    點擊back鍵關閉一個Activity時,生命週期的過程是: onPause(部分可見, 不可交互) -> onStop(完全不可見) -> onDestory(銷燬了)。
    當開啓一個新的Activity(以對話框形式),新的activity把後面的activity給蓋住一部分時, 後面的activity的生命週期執行的方法是:  onPause(部分可見, 不可交互)。
    當把新開啓的Activity(以對話框形式)給關閉時, 後面的activity的生命週期執行的方法是: onResume(可見, 可交互)。
    當開啓一個新的activity把後面的activity完全蓋住時, 生命週期的方法執行順序: onPause -> onStop(完全不可見)。
    當把新開啓的activity(完全蓋住)給關閉時, 生命週期的方法執行順序是: onRestart -> onStart -> onResume(可見, 可交互)。
    實際工作中使用的方法
    onResume 可見, 可交互. 把動態刷新的操作啓動.
    onPause 部分可見, 不可交互.  把動態刷新的一些操作, 給暫停了.
    onCreate 初始化一些大量的數據.
    onDestory 把數據給釋放掉, 節省內存.

    注:指定Activity以對話框的形式顯示的方法:在activity節點追加以下主題android:theme="@android:style/Theme.Dialog"。

   橫豎屏切換時,生命週期,默認情況下會把activity銷燬再創建。
   爲了不讓Activity銷燬在創建,可以在清單文件中進行如下配置:
   4.0以下版本--android:configChanges="orientation|keyboardHidden"
   4.0以上版本--android:configChanges="orientation|screenSize"
   兼容所有版本--android:configChanges="orientation|keyboardHidden|screenSize"

5. Activity啓動模式

   任務棧
   * 任務棧,是用來提升用戶體驗的。
   * 程序每次打開時就創建了一個任務棧,用於存儲當前程序的activity。
   * 所有的activity屬於一個任務棧。
   * 一個任務棧包含了一個activity的集合, 規定了如何去有序的選擇哪一個activity和用戶進行交互。
   * 只有在任務棧棧頂的activity纔可以跟用戶進行交互。
   * 任務棧可以移動到後臺, 並且保留了每一個activity的狀態. 並且有序的給用戶列出她們的任務, 而且還不丟失它們狀態信息,任務棧保存了每個activity轉到後臺時的狀態。
   * 退出程序: 把所有的任務棧中所有的activity清除出棧,任務棧銷燬。

   Android系統的默認任務棧存在的問題:
   * 用戶體驗差,需要點擊多次返回纔可以把程序退出了。
   * 數據冗餘,重複數據太多,會導致內存溢出的問題(OOM)。

   可以設置Android啓動模式改變Activity入棧/出棧方式:在清單文件中activity節點裏指定launchMode的屬性。
   launchMode可取值:
   standard,標準模式(activity的默認模式),導致上面的問題出現。
   singleTop,單一頂部模式: 如果一個activity的實例已經存在當前任務棧的棧頂, 系統會發送一個Intent給那個實例的onNewIntent()方法。
   應用場景: 防止別的程序惡意打開我們的頁面.  
   singleTask,單一任務棧模式: 如果activity的實例已經存在任務棧中, 系統就不會創建一個新的實例, 而是調用那個實例的onNewIntent()方法, 並且把那個已經存在的activity實例以上所有的activity給清除出棧, 把自己變成棧頂的效果。
   應用場景: 商品列表 -> 商品詳情 -> 圖片詳情 -> 大圖查看   想從大圖查看立刻回到商品列表, 並且把後面開啓的三個頁面關閉時。
   singleInstance,單一實例模式: 系統會創建一個新的任務棧把activity的實例放在新的任務棧的棧頂(棧底),其他的activity頁面如果要開啓這個activity也不會在這個任務棧中創建實例。
   如果activity的實例已經存在, 系統會調用那個實例的onNewIntent()方法。
   應用場景: 在整個系統中只需要初始化一次的界面。

雜記:
android長按主頁鍵,可打開最近打開的應用。
windows中alt+tab,打開當前所有任務。
android工程中有時出現2個清單文件,刷新一下就好了,eclipse本身的問題。
sdk/source/android-18是android4.3.jar的源碼,也就是android開發工具包的代碼。
android源碼,是整個操作系統的代碼。
各個應用的源碼在:4.0源碼/package/app中。

ctrl+f11,模擬器橫屏。
alt+shift+c/o javabean自動生成方法。
相對佈局下,控件居中用center屬性。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章