Android開發系列---Activity

来源:https://www.cnblogs.com/duhuamei/archive/2019/11/05/acitivity.html
-Advertisement-
Play Games

一. Android系統版本及詳細信息 最新數據 https://developer.android.com/about/dashboards/ 二. Android項目初探 1. 使用android studio創建一個工程 Application Name:“My First App” Comp ...


一.  Android系統版本及詳細信息

最新數據  https://developer.android.com/about/dashboards/

 

二.  Android項目初探

1.    使用android studio創建一個工程

Application Name:“My First App”

Company Domain:“example.com”

Project和module聯繫和區別

一個 Project 可以有多個 Module。目前主流的大型項目是多Module結構的,模塊之間彼此可以相互依賴。他們之間應該都是處於同一個項目業務情況下的模塊,彼此之間是有不可分割的業務關係的。

Android studio中,一個Project代表一個完整的APP,Module表示APP中的一些依賴庫或獨立開發的模塊。比如可以新建一個library做為module,然後在主APP上點右鍵 open module setting的Dependencies中添加一個模塊依賴。然後主APP中就可以使用module中的類了。

2.    目錄結構

Android視圖  

Project視圖

 

關於gradle.build文件參考: https://developer.android.google.cn/studio/build/index.html

3.    Logcat的使用

日誌列印工具

方法

級別

Log.v()

verbose

Log.d()

debug

Log.i()

info

Log.w()

warn

Log.e()

error

 

     註意:在android studio中創建一個activity 為我們完成了三步:(繼承自AppCompatActivity是為了向後相容)

創建activity、在menifest中註冊activity、創建activity對應的layout文件

4.    隱藏標題欄

方法一:

繼承自AppCompatActivity:

if (getSupportActionBar() != null){
    getSupportActionBar().hide();
}

 

方法二: 在style中加入如下代碼:    <item name="windowNoTitle">true</item>

5.    在活動中使用Toast

Toast.makeText(this,"you clicked",Toast.LENGTH_SHORT).show();

6.    在活動中添加菜單  

       (1)添加菜單xml文件:

<menu xmlns:android="http://schemas.android.com/apk/res/android">

<item

    android:id="@+id/add_item"

    android:title="add"/>

<item

    android:id="@+id/delete_item"

    android:title="delete"/>

</menu>

(2)重寫onCreateOptionsMenu方法

public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.main,menu);

        return true;  //返回true表示顯示該菜單

    }

(3)重寫onOptionsItemSelected

public boolean onOptionsItemSelected(MenuItem item){

        switch(item.getItemId()){

            case R.id.add_item:

                Toast.makeText(this,"add clicked",Toast.LENGTH_SHORT).show();

                break;

            case R.id.delete_item:

                Toast.makeText(this,"delete clicked",Toast.LENGTH_SHORT).show();

                break;

        }

        return true;

    }

更多詳情參見考:https://developer.android.google.cn/guide/topics/ui/menus

7.    銷毀活動

finish();   //第一講到此+java預備知識

三.  Android事件處理    

Android提供了兩套事件處理機制:監聽、回調

1.    基於監聽的事件處理

事件監聽的處理模型中,主要涉及三類對象:

Event Source(事件源)  通常是各個組件,如按鈕、視窗、菜單等;

Event(事件):事件封裝了界面組件上發生的特定事情。

Event Listener(事件監聽器):負責監聽事件源所發生的事件,並對各種事件作出相應的相應。

 

事件監聽涉及的三個問題:

事件源:     任何組件都可作為事件源。

事件監聽器:由程式員實現,關鍵是實現處理方法。

註冊監聽器:調用事件源的setXxxListener方法即可。

 

另外:對於鍵盤事件、觸摸屏事件等,此時程式需要獲取事件發生的詳細信息。如,鍵盤事件獲取是哪個鍵觸發的,觸摸屏事件需要獲取事件發生的位置的,Android會將事件信息封裝成XxxEvent對象,並將該對象作為參數傳遞給事件處理器。

 

所謂事件監聽器,其實就是實現了特定介面的java類的實例。實現事件監聽器,通常有如下幾種形式:

l  內部類

l  匿名內部類

l  外部類

l  Activity本身作為事件監聽器

l  直接綁定到標簽

其他事件如下表所示:

void

setOnClickListener(View.OnClickListener l)

Register a callback to be invoked when this view is clicked.

void

setOnContextClickListener(View.OnContextClickListener l)

Register a callback to be invoked when this view is context clicked.

void

setOnCreateContextMenuListener(View.OnCreateContextMenuListener l)

Register a callback to be invoked when the context menu for this view is being built.

void

setOnDragListener(View.OnDragListener l)

Register a drag event listener callback object for this View.

void

setOnFocusChangeListener(View.OnFocusChangeListener l)

Register a callback to be invoked when focus of this view changed.

void

setOnGenericMotionListener(View.OnGenericMotionListener l)

Register a callback to be invoked when a generic motion event is sent to this view.

void

setOnHoverListener(View.OnHoverListener l)

Register a callback to be invoked when a hover event is sent to this view.

void

setOnKeyListener(View.OnKeyListener l)

Register a callback to be invoked when a hardware key is pressed in this view.

void

setOnLongClickListener(View.OnLongClickListener l)

Register a callback to be invoked when this view is clicked and held.

void

setOnScrollChangeListener(View.OnScrollChangeListener l)

Register a callback to be invoked when the scroll X or Y positions of this view change.

void

setOnTouchListener(View.OnTouchListener l)

Register a callback to be invoked when a touch event is sent to this view.

 

2.    基於回調的事件處理  

當用戶在GUI組件上激發某事件時,組件自己的特定方法負責處理該事件。方法是自定義控制項使其繼承GUI組件類,在自定義控制項中重寫事件處理方法。

Demo

l  基於回調的事件傳播

幾乎所有基於回調的事件處理方法都有一個boolean類型的返回值,用於標誌該處理方法是否已完全處理該事件。

返回true,表明已處理完,不會傳播出去。

返回false,表明未處理完,會傳播出去。

幾種方法調用的先後順序: 組件的監聽器à組件自身的回調方法à組件所在Activity的回調方法。其中任何一個事件處理方法返回了true,那麼該事件將不會繼續向外傳播。

 

四.  啟動活動的方法:

1.    顯式Intent   demo

//第一個參數Context是啟動活動的上下文,第二個參數是制定要啟動的目標活動。

Intent intent=new Intent(MainActivity.this,SecondActivity.class);

startActivity(intent);

2.    隱式Intent   demo

不明確指定啟動哪一個活動,而是指定一系列action 和category,由系統分析啟動哪一個活動。只有<action>和<category>中的內容同時能匹配上Intent中指定的action和category時,這個活動才能響應該Intent。

       每個Intent只能指定一個action,但可以指定多個category。如果沒有匹配的活動可以啟動程式將崩潰;如果有多個匹配的活動,系統將提供列表讓用戶選擇啟動哪個活動。

 

顯示引用不能啟動其他進程的Activity對象,因為無法獲取其他進程的Activity對象的位元組碼,而隱式啟動則可以通過配置Intent Filter啟動其他進程的Activity對象,因此在應用內,我們一般都是使用顯示啟動的方式啟動Activity,而如果需要啟動其他應用的Activity時,一般使用隱式啟動的方式。

l  更多隱式Intent的用法

       調用系統的瀏覽器打開一個網頁。

       Intent intent=new Intent(Intent.ACTION_VIEW);

intent.setData(Uri.parse("http://www.baidu.com"));

Uri.parse() 將字元串解析成一個Uri對象。setData() 方法接收一個Uri對象,指定當前Intent正在操作的數據。

只有<data>標簽中指定的內容和Intent中攜帶的data完全一致時,當前活動才能相應該Intent.

<data>  使用一個或多個指定數據 URI 各個方面(schemehostportpath 等)和 MIME 類型的屬性,聲明接受的數據類型。

https://developer.android.google.cn/guide/components/intents-common#Browser

五.  活動之間傳遞數據

1.    向下一個活動傳遞數據

        Intent intent=new Intent(MainActivity.this,SecondActivity.class);

intent.putExtra("extraData_Key","I am data");

        startActivity(intent);

在下一個活動中將數據取出:

Intent intent=getIntent();

        String data=intent.getStringExtra("extraData_Key");

使用Bundle

兩個Activity交換數據通過Intent完成,只需將交換的數據放入Intent中即可。

putExtra(String key, Xxx  value)     向Intent中按key-value對的形式存入數據

Xxx getXxxExtra(String key)         從Intent中按key取出指定類型的數據

putExtras(Bundle data)           向Intent中存入攜帶數據的Bundle

Bundle  getExtras()             從Intent中取出攜帶數據的Bundle

 

向Bundle對象中存取數據:

putXxx(String key, Xxx data)   向Bundle中放入Xxx類型的數據

Xxx  getXxx(String key)       從Bundle中取出Xxx類型的數據

putSerializable(String key, Serializable data)   向Bundle中放入一個可序列化的對象

Serializable  getSerializable(String key)      從Bundle中取出可序列化對象

2.    返回數據給上一個活動

1)     啟動活動時使用onActivityResult方法:

startActivityForResult(intent,1);

2)     重寫onActivityResult()方法,對返回的數據進行處理:

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

 {

switch (requestCode){

        case 1:

            if(resultCode==RESULT_OK) {

                String returnedData=data.getStringExtra("data_return");

                Log.d(TAG, "onActivityResult: "+returnedData);

            }

            break;

    }

}

3)     在第二個活動中返回數據:

    setResult(RESULT_OK,intent);

finish();

 

六.  活動的生命周期

1.    返回棧(Back Stack)

每啟動新的活動,就會覆蓋在原來的活動上,按Back鍵會銷毀上面的活動,下麵的活動就會重新顯示出來。

       Android使用Task來管理活動,一個Task就是一組存放在棧里的活動的集合,這個棧被稱為返回棧(Back Stack)。參見activity返回棧

2.    活動狀態

l  運行狀態

l  暫停狀態

l  停止狀態

l  銷毀狀態

3.    活動的生存期

 

4.    體驗活動的生命周期  (Demo:  ActivityLifeCycle)

5.    活動被回收了怎麼辦

由於記憶體不足等原因,處於停止狀態的活動有可能被系統回收。當該活動重新可見時,該活動會被重新創建。

onSaveInstanceState()方法在活動被回收之前調用,解決活動被回收時保存臨時數據的問題。

1) 活動回收前保存數據

protected void onSaveInstanceState(Bundle outState) {

   outState.putString("data_key","I am data");  //保存數據

super.onSaveInstanceState(outState);//必須調用父類的方法

}

2) 活動恢復時恢複數據

在onCreate方法中恢復:

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); // Always call the superclass first

    if (savedInstanceState != null) {

        String str=savedInstanceState.getString("data_key");//得到數據

        Log.d("MainActivity", "活動恢復,數據為:"+str);

    } else {

        Log.d("MainActivity", "這是活動正常啟動");

    }

//……

}

在onRestoreInstanceState方法中恢復:

protected void onRestoreInstanceState(Bundle savedInstanceState) {

super.onRestoreInstanceState(savedInstanceState);//可選

String str=savedInstanceState.getString("data_key");//得到數據

Log.d("MainActivity", "恢複數據為:"+str);

}

註意:Always call the superclass implementation of onRestoreInstanceState() so the default implementation can restore the state of the view hierarchy.

開發者可根據具體情況選擇在哪個方法中進行恢復。

3) onSaveInstanceState() 何時被執行

當某個activity變得“容易”被系統回收時,該activity的onSaveInstanceState就會被執行,除非該activity是被用戶主動銷毀的,例如當用戶按BACK鍵(手機下方的返回鍵)的時候。(why)分為以下幾種情況:

從第一個界面跳轉到第二個界面,第一個界面就會執行onSaveInstanceState

按下home鍵,運行多個其他程式,這時系統不確定會不會將該activity銷毀,所以會執行onSaveInstanceState方法保存值。

關閉手機屏幕時

屏幕方向切換時,例如從豎屏切換到橫屏時。(前提是androidMenifest.xml中對應activity標簽沒有配置<activity android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|screenSize"></activity>)

4) onRestoreInstanceState() 何時被執行

Activity被系統回收後,當重新恢復時會調用onRestoreInstanceState(),並且是在onStart()之後。The system calls onRestoreInstanceState() only if there is a saved state to restore, so you do not need to check whether the Bundle is null。

       而系統創建一個新的Activity實例或重新創建一個以前的實例時都會調用onCreate(),因此在onCreate()中需要判斷Bundle是否為null。

5) 模擬當前應用被系統回收

進入開發者選項,選中不保留活動。 

 

6) 為什麼我們的UI界面的值不用我們自己保存也可以自動保存,狀態恢復呢?

開發者只需要為這些控制項指定一個唯一的ID,剩餘的事情就可以自動完成了。如果沒有為控制項指定ID,則這個控制項就不會進行自動的數據保存和恢復操作。

 

更多參考:https://developer.android.google.cn/guide/components/activities/activity-lifecycle.html#saras

另外,onSavedInstanceState()只適合保存少量可序列化的數據。use a combination of ViewModel objects, the onSaveInstanceState() method, and/or local storage to persist the UI state across such application and activity instance transitions. 

 

6.    活動的載入模式(Launch Mode)

Often, the way Android manages tasks and the back stack by placing all activities started in succession in the same task and in a "last in, first out" stack.

 

You can interrupt the normal behavior, with attributes in the <activity> manifest element and with flags in the intent that you pass to startActivity().

Launch modes allow you to define how a new instance of an activity is associated with the current task. 

<activity android:name=".SecondActivity" android:launchMode="singleTop"/>

 

standard (the default mode)

無論當前棧頂是哪一個Activity都會開始一個新的Activity。

singleTop

如果需要創建的Activity已經處於任務(Task)棧頂時,復用該Activity。

singleTask

需要創建的Activity已經處於任務(Task)棧時,彈出此Activity上的所有其他Activity,復用該Activity。

singleInstance

啟動一個新的任務(Task)棧,且該任務棧中只有這唯一一個Activity。整個系統中創建了該Activity,將不再重新創建。

當從返回棧回退時,如果當前回退棧為空了,才會顯示另一回退棧的活動。

Demo四種啟動模式演示

 

onNewIntent方法的使用

除了standard模式,其他三種方式都可能存在復用Activity的情況。通過Intent啟到一個Activity,如果系統已經存在一個實例,系統就會將請求發送到這個實例上,但新的Intent請求可能要處理新的數據,而這時沒有機會調用onCreate方法,怎麼辦呢?系統為我們準備了onNewIntent方法。

一般,通過在onCreate和onNewIntent方法中調用同一個處理數據的方法,使得不管是創建新的Activity實例,還是復用原來的Activity實例,處理數據的方式保持一致。如下所示:

public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    processExtraData();

 }

 

protected void onNewIntent(Intent intent) {

   super.onNewIntent(intent);

    setIntent(intent);//must store the new intent unless getIntent() will return the old one

   processExtraData();

 }

 

private void processExtraData(){

    Intent intent = getIntent();

    //use the data received here

 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 創建表空間及用戶CREATE TABLESPACE OracleDBFDATAFILE 'D:\app\zhoulx\oradata\bdc\OracleDBF.DBF' SIZE 100M AUTOEXTEND ON NEXT 20M MAXSIZE UNLIMITED -- 這裡是你設置資料庫存 ...
  • 1.select * from SYS_DICT as of timestamp to_timestamp('2019-11-05 10:00:00','yyyy-mm-dd hh24:mi:ss'); 時間點在刪除數據之前,又儘量精確 sys_dict 是表名 2.insert into SYS_ ...
  • 阿裡開發手冊的描述,禁止多表join: 手冊上寫著【強制】,相信很多同學項目裡面的代碼都不滿足這個要求。 但是關鍵問題是:不用join,這SQL究竟要怎麼寫?! 分解關聯查詢 即對每個要關聯的表進行單表查詢,然後將結果在應用程式中進行關聯。下麵的這個查詢: 可以分解成下麵這些查詢來代替: 但是該方案 ...
  • 基本環境 elasticsearch版本:6.3.1 客戶端環境:kibana 6.3.4、Java8應用程式模塊。 其中kibana主要用於數據查詢診斷和查閱日誌,Java8為主要的客戶端,數據插入和查詢都是由Java實現的。 案例介紹 使用elasticsearch存儲訂單的主要信息,docum ...
  • 前幾天,看到一個群友用WITH ROLLUP運算符。由於自個兒沒用過,看到概念及結果都雲里霧裡的,所以突然來了興趣對生成結果測了一番。 一、概念: WITH CUBE:生成的結果集顯示了所選列中值的所有組合的聚合。 WITH ROLLUP:生成的結果集顯示了所選列中值的某一層次結構的聚合。 GROU ...
  • 一、MySQL於keepalived簡介** 前言: 在企業中,資料庫高可用一直是企業的重中之重,中小企業很多都是使用mysql主從方案,一主多從,讀寫分離等,但是單主存在單點故障,從庫切換成主庫需要作改動。因此,如果是雙主或者多主,就會增加mysql入口,增加高可用。不過多主需要考慮自增長ID問題 ...
  • 看了下上一次寫博客已經是2年前了,很是慚愧,那麼這兩年我都幹了些什麼呢,由於18年的經濟不景氣,我們一家創業5年的公司解散,我也算是最後一批走的老員工吧,很是不捨得,畢竟,產品打磨了5年,最後還是輸給了資本(有空寫一下創業5年的見聞以及失敗原因)。 創業公司出來後,我加入了一下App出海的公司,主營 ...
  • 出現如下錯誤:DDMS files not found: xxx\hprof-conv.exeThe connection to adb is down, and a severe error has occuredPlease ensure that adb is correctly locate... ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...