Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 關於Activity的一些要點(2)

關於Activity的一些要點(2)

編輯:關於Android編程

一、帶返回值的Activity回退過程

一般情況下,我們要從當前Activity跳轉到另一個Activity,采用的方法是通過startActivity(Intent)來攜帶數據並實現跳轉
有時候又需要跳轉到的Activity能夠在回退時返回處理結果給前一個Activity,這就要用到以下方法了

public void startActivityForResult(Intent intent, int requestCode)

該方法同樣是用於實現Activity的跳轉,不過多了一個int類型的請求碼requestCode
requestCode用於標示當Activity回退時,處理結果是從哪一個Activity傳遞來的,因為當前Activity有可能需要跳轉到多個Activity

此外,Activity類還包含有以下方法

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

requestCode即是請求碼,resultCode用於標示數據處理結果,data用於攜帶數據

因此,我們可以用以下代碼實現Activity的跳轉

        private int REQUEST_CODE = 10;

        Intent intent = new Intent(MainActivity.this, Main2Activity.class);
        Bundle bundle = new Bundle();
        bundle.putString("requestText", "啊哈");
        intent.putExtras(bundle);
        startActivityForResult(intent, REQUEST_CODE);

向Intent中傳入需要傳遞給Main2Activity的數據

然後,在onActivityResult中處理Main2Activity回退後傳遞而來的數據處理結果,這裡用Log來輸出

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
            Bundle bundle = data.getExtras();
            Log.e("MainActivity", bundle.getString("responseText"));
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

其中,需要判斷requestCode是否與請求碼相等
此外,查看源碼可知,resultCode取值一般為以下三個,用來標示操作結果

    /** Standard activity result: operation canceled. */
    //標示操作取消
    public static final int RESULT_CANCELED    = 0;

    /** Standard activity result: operation succeeded. */
    //標示操作成功
    public static final int RESULT_OK           = -1;

    /** Start of user-defined activity results. */
    public static final int RESULT_FIRST_USER   = 1;

以上都是在MainActivity中操作,此外還需要在Main2Activity中設置返回結果
先取出傳遞而來的數據requestText

    private String requestText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Intent intent = getIntent();
        if (intent != null) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                requestText = bundle.getString("requestText");
            }
        }
        init();
    }

通過setResult方法設置處理結果為RESULT_OK,並通過intent攜帶處理結果

public void init() {
        findViewById(R.id.response).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                Bundle bundle = new Bundle();
                bundle.putString("responseText", "收到第一個Activity的請求內容為:" + requestText);
                intent.putExtras(bundle);
                setResult(RESULT_OK, intent);
                finish();
            }
        });
    }

這樣就可以實現當Activity回退時,攜帶處理結果到前一個Activity了


二、關於Activity啟動模式的補充說明
在上一篇博文中已經介紹過Activity的四種啟動模式了,這裡再來補充一些內容

singleTask
此為棧內復用模式
如果以在AndroidManifest中聲明屬性的方式來設定啟動模式的話,如果不指定taskAffinity屬性,該Acitvity只會存在於當前棧中
想要讓Activity以單實例的方式存在於一個新的棧的話,可以這樣聲明:
    

注意,taskAffinity的值不能與包名相同,不然就相當於沒有設置了

可以通過getTaskId()方法來查看當前Activity位於哪個棧,如:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("第一個Activity", getTaskId() + "");
    }
singleInstance
即單實例模式
采用此種模式的Activity均會獨立存在於一個棧內,即使兩個Activity的taskAffinity屬性相同
例如
    
    

Main2Activity和Main3Activity均聲明為singleInstance模式且棧名為com.custom.czy
但通過Log.e("Activity", getTaskId() + "");查看,還是可以發現兩個Activity存在於不同的棧中

三、Activity的隱式調用
隱式調用不需要明確指定要調用的Activity信息,而是根據Intent具有的信息去匹配目標組件的IntentFilter中所設置的過濾信息,如果匹配成功則啟動,否則會報錯
一個Activity可以包含有多個IntentFilter,只要Intent能夠匹配其中一組< intent-filter >即可啟動該Activity
IntentFilter具有的屬性有:action、category、data

action
action屬性值是一個字符串,系統也為我們提供了多個action,如Intent.ACTION_VIEW可用於打開系統自帶的浏覽器
< intent-filter >中可以聲明多個action,只要求Intent中攜帶的action字符串與其中一個相同即成功匹配該Activity
Intent中必須含有action屬性,否則將直接匹配失敗
不過在Intent總設置action時,我試了下,似乎只可以定義一個action,通過構造函數或者setAction(String action)函數來定義action,多次設置只會保留最後一個action值

        
        
        

        
    public void startActivity(View view) {
        Intent intent = new Intent("com.bb.hh");
        intent.setAction("com.czy.action");
        Log.e("++++++", intent.getAction());
        startActivity(intent);
    }

這樣依然可以成功啟動Activity

category
< intent-filter >中同樣可以設定多個category屬性,且Intent也可以通過addCategory(String category)添加多個category
與action屬性不同的是,只要是在Intent中包含的category值,< intent-filter >都必須有category與之一一匹配,否則匹配失敗

需要注意的是,系統在startActivity(Intent intent)的時候,會自動為Intent添加一個默認的category值,即:android.intent.category.DEFAULT
所以為了讓Activity可以通過隱式調用的方式啟動,需要在< intent-filter >同樣為之添加一個默認的category值
如上述代碼所示

data
data屬性用於指定當前活動能夠響應什麼類型的數據
如系統自帶的浏覽器自然就能響應http模式的網絡連接要求,因此我們可以用隱式調用的方式來調用浏覽器打開指定網頁
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(Uri.parse("http://www.baidu.com"));
    startActivity(intent);

如果過濾規則中設置了data屬性,則Intent中也必須含有data屬性且相同才能匹配成功
data包含的屬性值有:

    

data由兩部分組成,mimeType和URI
mimeType指媒體類型,可以是:image/jpeg、video/*,用於表示圖片、文本、視頻等不同的媒體格式
URL的結構如下所示:
< scheme>://< host>:< port>/[< path>|< pathPrefix>|< pathPatten>]

scheme:URI的模式,如http,file,content,默認值為(content和file)
host:URI的主機名,比如www.baidu.com
port:URI的端口號
path、pathPatten和pathPrefix這三個參數表示路徑信息

如,可以設置某Activity能夠處理的數據類型為圖片image

 
    
        
        
        

        
        

        

    

則可以通過設置mimeType屬性來啟動該Activity

    public void startActivity(View view) {
        Intent intent = new Intent("com.bb.hh");
        intent.setAction("com.czy.action");
        intent.addCategory("android.intent.category.czy");
        intent.setType("image/png");
        startActivity(intent);
    }

或者為Intent設置完整的data屬性

    public void startActivity(View view) {
        Intent intent = new Intent("com.bb.hh");
        intent.setAction("com.czy.action");
        intent.addCategory("android.intent.category.czy");
        intent.setDataAndType(Uri.parse("file://abc"),"image/png");
        startActivity(intent);
    }

此外,由於通過隱式調用有可能因為匹配不成功而導致報錯,所以在調用之前可以先判斷當前是否有合適的Activity

Intent intent = new Intent("com.bb.hh");
        intent.setAction("com.czy.action");
        intent.addCategory("android.intent.category.czy");
        intent.setDataAndType(Uri.parse("file://abc"), "image/png");

        ComponentName componentName = intent.resolveActivity(getPackageManager());
        if (componentName != null) {
            String name = componentName.getClassName();
            Log.e("MainActivity:", "匹配成功:" + name);
            startActivity(intent);
        } else {
            Log.e("MainActivity:", "匹配失敗");
        }

如果匹配失敗,resolveActivity方法就會返回null,否則就會返回匹配度最高的Activity信息

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved