1. 程式人生 > >Android學習(一)

Android學習(一)

分析 構建 新的 studio 字符串解析 ble 學習 nullable android學習

Android 系統架構

  1. linux內核層
  2. 系統運行庫層
  3. 應用框架層
  4. 應用層

Android 的四大組件

  • 活動(Activity)
  • 服務(Service)、
  • 廣播接收器(Broadcast Receiver)
  • 內容提供器(Content Provider)

手動創建一個活動

  1. 在Android Studio中創建一個Android程序選擇 Add No Activity
  2. 在 app/src/main/java/默認包名 中 右鍵 New一個Empty Activity會彈出一個對話框 將活動命名為 FirstActivity 並且不勾選Generate Layout File 和 LauncherActivity這兩個選項

    勾選Generate Layout File會自動為FirstActicy生成一個對應的布局文件

    勾選LauncherActivity會設置當前的活動為項目主活動。

    勾選BackWards Compatibility表示會為項目啟動向下兼容模式

  3. 任何活動都應該重寫Activity的onCreate()方法 Android Studio已經幫我們做完了。

  4. 創建和加載布局 在app/src/main/res 目錄 new 一個Directory創建一個名為layout的目錄 然後右鍵 new 一個Layout resource file 在彈出窗口中命名為first_layout
  5. 回到FirstLayout中的onCreate()方法加入 setContentView(R.layout.first_layout);
  6. 在AndroidManifest文件中註冊 在application標簽中加入標簽並且指定action和category

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    

Toast

Toast是一種提醒方式 使用方法是:

Toast.makeText(FirstActivity.this,"提醒文字",Toast.LENGTH_SHORT).show();
Toast通過其靜態方法創建一個Toast對象,然後通過調用show()方法將Toast顯示出來

在活動中使用Menu

  1. 在res目錄下新建一個menu文件夾。然後在這個文件夾傷新建一個Menu resource file輸入文件名mian點擊ok
  2. 在文件main.xml中的menu標簽中輸入

    <item
        android:id="@+id/add_item"
        android:title="添加"/>
    <item
        android:id="@+id/remove_item"
        android:title="刪除"/>
    
  3. 這樣就創建了兩個菜單項標簽就是用來創建具體的某一個菜單項

  4. 回到FirstActivity中重寫onCreateOptionsMenu()方法快捷鍵Ctrl+o具體如下

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main,menu);
        return true;
    }
    通過getMenuInflater()方法能夠得到MenuInflater對象,再調用他的inflate()方法就可以給當前的活動創建菜單了
    inflater()方法接受兩個參數,第一個參數表示通過哪一個資源文件創建菜單,所以傳入剛才創建的main.xml第二個參數用於指定我們的菜單項將添加到哪一個Menu對象當中去這裏直接使用oncreateOptionsMenu()方法中傳入的menu參數,然後給這個方法返回true 表示允許菜單顯示出來, 如果返回了false創建的菜單將會無法顯示。
    
  5. 創建菜單的響應事件 通過重寫onOptionsItemSelected()方法

    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
            case R.id.add_item:
                Toast.makeText(FirstActivity.this,"點擊了菜單中的添加", Toast.LENGTH_SHORT).show();
                break;
            case R.id.remove_item:
                Toast.makeText(FirstActivity.this, "點擊了菜單中的刪除", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }
    在onOptionsItemSelected()方法中通過調用item.getItemId()來判斷我們點擊的是哪一個菜單項
    

銷毀一個活動

Activity中提供了一個finish()方法來銷毀當前活動。

Intent

顯式Intent

  1. 在創建一個 Activity 命名為SecondActivity 然後在FirstActivity中添加一個按鈕
  2. 在FirstActivity中添加按鈕監聽事件後加入如下代碼

     protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.first_layout);
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                    startActivity(intent);
                }
            });
        }
    我們首先構建出了一個Intent 傳入FirstActivity.this作為上下文, 傳入SecondActivity.class 作為活動目標,這表示在FirstActivity這個活動的基礎上打開SecondActivity這個活動,然後通過startActivity方法來啟動這個Intent
    

隱式Intent

隱式Intent相對於顯式Intent制定了一些列更為抽象的action和category等信息,然後交由系統去分析這個Intent

在AndroidManifest.xml中,的activity標簽下配置的內容可以指定當前活動能夠相應的action和category。

    SecondActivity的activity中添加相應
    <intent-filter>
        <action android:name="balabala.balabala.ACTION_START" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
    FirstActivity.java修改如下:
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent("balabala.balabala.ACTION_START");
            //其中的action需要與AndroidManifest.xml中action標簽中一致。
            startActivity(intent);
        }
    });

    在action標簽中我們指明了當前活動可以響應balabala.balabala.ACTION_START這個action 而category標簽則包含了一些附加信息,更精確的指明了當前的活動能響應的Intent中還可能帶有category只有<action>和<category>中的內容同時能夠匹配上Intent中指定的action和category時這個活動才能響應這個Intent
    android.intent.category.DEFAULT是一種默認的category,在調用startActivity()方法的時候會自動將這個category添加到Intent中
    每個Intent中只能指定一個action,但是卻能指定多個category。

添加一個category:
在intent聲明後添加

intent.addCategory("labalaba.labalaba.MY_CATEGORY");

調用了Intent類中的addCategory方法來添加一個category,我們制定了一個自定義的category 值為 labalaba.labalaba.MY_CATEGORY

然後在AndroidManifest.xml中,的activity標簽下配置

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="balabala.balabala.ACTION_START" />
        <!--android.intent.category.DEFAULT使一種默認的category在調用startActivity會自動將這個category添加到Intent中 所以必須要有這一句-->
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="labalaba.labalaba.MY_CATEGORY" />
    </intent-filter>
</activity>
更多的Intent的用法

使用隱式Intent不僅可以啟動自己程序內的活動,還可以啟動其他程序的活動,這樣就可以使多個程序之間的功能共享成為一種可能。
修改FirstActivity中按鈕點擊事件的代碼 如下:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://www.zbuter.cn"));
        startActivity(intent);
    }
});
這裏制定了Intent的action是Intent.ACTION_VIEW 這是一個Android系統內置動作,其常量為android.intent.action.VIEW 然後通過Uri.parse()方法將一個網址字符串解析成一個Uri對象,在調用Intent的setData()方法將這個Uri對象傳遞進去
除了http協議外還可以指定很多其他協議,比如geo表示顯式地理位置、tel表示撥打電話。。。
我們也可以在AndroidManifest.xml中註冊對應action使我們自己的程序也響應這動作

向下一個活動傳遞數據

向下一個活動傳遞數據

intent.putExtra("key", "value");
可以向要啟動的Activity中添加額外的數據 

接受上一個活動傳遞來的數據

在啟動的Activity中獲取上個活動傳遞的數據要使用    
Intent intent = getIntent();
String data = intent.getStringExtra("key");
將可以獲得上一個活動傳遞來的key所對應的數據
如果key對應的是int類型就可以使用intent.getIntExtra()方法來或的int類型的返回值。

返回數據給上一個活動。

在啟動Activity時使用
startActivityForResult(intent,1);
第二個參數是請求碼

在SecondActivity中添加返回數據的邏輯

button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.putExtra("data_return", "Hello FirstActivity");
            setResult(RESULT_OK, intent); 
            finish(); //結束當前Activity
        }
    });
setResult接受兩個參數,第一個參數用於向上一個活動的返回處理結果,一般只用RESULT_OK和RESULT_CANCELED這兩個值,第二個參數則把帶有數據的Intent傳遞過去。

由於我們使用的是startActivityForResult()方法來啟動SecondActivity的在SecondActivity被銷毀之後會調用上一個活動的onActivityResult()方法所以我們需要在FirstActivity中重寫這個方法來得到返回的數據。

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    switch(requestCode){
        case 1:
            if(resultCode == RESULT_OK){
                String returnData = data.getStringExtra("data_return");
                Log.i(TAG, "onActivityResult: "+returnData);
            }
    }
}

Activity的生命周期

活動的狀態

  • 運行狀態
  • 暫停狀態
  • 停止狀態
  • 銷毀狀態

Activity的生存期:

Activity類中定義了7個回調方法, 覆蓋了活動生命周期的每一個環節,

onCreate() 他會在活動第一次被創建的時候調用,一般在這個方法中完成對Activity的初始化操作,比如加載布局、綁定事件等。
onStart() 這個方法在活動由不可見變為可見時調用。
onResume() 這個方法在活動準備好了和用戶進行交互的時候調用。此時的活動一定位於返回棧的棧頂。並且處於運行狀態。
onPause() 這個方法在系統準備去啟動或恢復另一個活動的時候調用。我們通常會在這個方法中將一些小號CPU資源釋放掉,以及保存一些相關的數據,但是這個方法一定要執行的速度快,不然會影響到新的棧頂活動的使用
onStop() 這個方法在活動完全不可見的時候調用,和onPuase()方法的區別是,如果啟動的活動是一個對話框活動,那麽onPause()方法會得到執行,而onStop()不會
onDestory()這個方法在活動被銷毀之前調用,之後的狀態將變為銷毀狀態。
onRestart()這個方法在活動由停止狀態變為運行狀態之前調用,也就是活動被重新啟動了。
以上7個方法除了onRestart()方法,其他都是兩兩對應的,可以分為三種生存周期。
完整生存期
活動在 onCreate() 和onDestroy()方法之間所經歷的,程序會在onCreate()中初始化各種操作,在onDestroy()釋放各種資源
可見生存期
活動在 onStart() 和onStop()方法之間所經歷的
前臺生存期
活動在 onResume() 和onPause()方法之間經歷的

活動的啟動模式

活動的啟動模式一共由4種

  • standard

    standard是活動默認的啟動模式,在不進行顯式指定的情況下所有的活動都會自動使用這種啟動模式在standard模式下系統不會在乎這個活動是否已經存在返回棧中, 每次啟動都會創建該活動的一個新的實例對象。
    
  • singleTop

    當活動啟動模式指定為singleTop時 在啟動時如果發現返回棧的棧頂已經是該活動,則直接使用這個活動不會創建新的實例。,
    
  • singleTask

    當活動啟動模式指定為singTask時,在啟動時候系統首先會在返回棧中檢查是否存在該活動的實例,如果發現已經存在則直接使用這個實例,並把這個活動之上的所有活動統統出棧,如果占中沒有這個活動則會創建一個新的活動實例
    
  • singleInstance

可以使在AndroidManifest.xml中通過標簽指定android:launchMode屬性類選擇啟動模式

Tips:
  • 知曉當前是在哪一個活動

    新建一個JAVA類起名為BaseActivity類讓BaseActivity繼承AppCompatActivity並重寫onCreate()方法
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity", getClass().getSimpleName());
    }
    

    然後讓其他Activity繼承BaseActivity, 就可以在logcat中觀看是當前活動的是哪一個進程了。

  • 隨時隨地退出程序

    當程序由多層活動時退出程序需要按好多下back鍵才可以退出。Home只是將程序掛起。
    所以應該新建一個ActivityCollector類作為活動管理器如下:

    public class ActivityCollector {
        public static List<Activity> activities = new ArrayList<>();
        public static void addActivity(Activity activity){
            activities.add(activity);
        }
        public static void removeActivity(Activity activity){
            activities.remove(activity);
        }
        public static void finishAll(){
            for (Activity activity: activities) {
                if(!activity.isFinishing()){
                    activity.finish();
                }
            }
        }
    }
    

    然後可以在BaseActivity中的onCreate()方法中插入一句
    ActivityCollector.addActivity(this);
    在onDestroy()方法中插入一句
    ActivityCollector.removeActivity(this);

    這樣不管在什麽地方想要退出程序 只需要調用ActivityCollector.finishAll()方法就可以了



來自為知筆記(Wiz)

Android學習(一)