安卓學習日誌 — Day02

概述

今日學習內容如下:

  • 瞭解 Miwok 語言應用的結構,在該應用中創建多屏,並使用 Intents 將多個 Activity 連接起來。
  • 視圖回收
    • 使用 LinearLayout 和 TextView 展示數據
    • 改用 ListView 和 ArrayAdapeter 展示數據
  • Memory Profiler 使用
  • ……

Miwok應用構建

應用概述

Miwok 是一個用來學習 Miwok語言的應用,應用打開後應該有四個可選的類別,分別爲Numbers、Family Members、Colors、Phrases。當點擊任意一個類別所在的區域時,將跳轉到該類別所在的頁面。

結構大概像下面這樣:

在這裏插入圖片描述

添加Activity

分別爲四個類別新建 Activity,鼠標右擊 --> New --> Activity --> EmptyActivity

在這裏插入圖片描述

在首頁中爲每個類別創建選項,這裏使用 LinearLayout 和 TextView:

在這裏插入圖片描述

OnClickListener

現在需要,當在首頁點擊某個類別時跳轉到該類別所在的頁面,這就需要監聽 視圖的 Onclick事件,而監聽事件需要用到監聽器,官方已經定義好了事件的監聽器。

下面直接使用,在首頁源碼(MainActivity)的 OnCreate 方法方法中添加:

        // Find the View that show the number category
        TextView numbers = (TextView) findViewById(R.id.numbers);
        // Set a clickListener on that View
        numbers.setOnClickListener(new View.OnClickListener() {
   
   
            // …………
        });

首先使用 findViewById(R.id.numbers) 獲取到了 Numbers 類別的視圖,然後調用 numbers.setOnClickListener() 方法爲視圖設置 OnClick 事件的監聽器,它接收 一個 OnClickListener 的實例。

監聽器是一個 interface(接口),因此我們需要按照接口中預定義的來實現這個接口,單擊事件監聽器 OnClickListener 接口中只包含一個方法 void onClick(View v);,因此單擊跳轉 Activity 的代碼如下:

      numbers.setOnClickListener(new View.OnClickListener() {
   
   
            // The code in this method will be executed when the family category is clicked on.
            @Override
            public void onClick(View view) {
   
   
                // Create a new intent to open the {@link NumbersActivity}
                Intent numbersIntent = new Intent(MainActivity.this, NumbersActivity.class);
                // Start the new activity
                startActivity(numbersIntent);
            }
        });

首先在 OnClickListener 的實現類中 重寫 onClick 方法,並在裏面定義視圖單擊時需要執行的操作。

onClick 方法中一共兩行代碼,第一行創建了一個 Intent 實例,傳入兩個參數 上下文環境 Context 和 目標Activity(這是一個顯式的 Intent),表示將要跳轉到 NumbersActivity 頁面;第二行代碼 則啓動這個 Intent 實例,執行真實的 跳轉操作。

四個類別的頁面跳轉也是一樣的,分別創建並設置 單擊事件的監聽器並 使用 Intent 讓其跳轉套不同的 頁面即可,代碼省略…………。

修改Activity顯示的名稱

有一個問題,在創建 Miwok 項目時指定 App Name 爲 Miwok,而沒有爲每個Activity定義 顯示的名稱,所以默認採用了應用的名稱,在 AndroidManifest.xml 中:

在這裏插入圖片描述

想要自定義 Activity 的名稱,可以更改 activity 標籤中的屬性來實現,如 指定 label 屬性的值即可更改相應的 Activity 顯示的名稱

在這裏插入圖片描述

視圖回收

LinearLayout 和 TextView

在 Numbers 頁面中需要顯示 1 到 10 的語言列表,因此考慮使用 線性佈局 加 TextView 來實現:

在 Numbers 頁面的佈局文件中定義一個 id 爲 rootView 的 LinearLayout,它將用於垂直排列 1 到 10 的 TextView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".NumbersActivity" />

在 Numbers 頁面的 OnCreate 方法中 填加代碼 實現,先通過 findViewById 方法獲取到根視圖LinearLayout的實例,然後 創建一個 TextView 實例傳入 this (當前Activity)作爲上下文並設置 Text,最後調用根視圖的 addView 方法將 TextView 添加進去,循環10次就添加了10個數字。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_numbers);

        LinearLayout root = (LinearLayout) findViewById(R.id.rootView);
        for (int i = 0; i < 10; i++) {
   
   
            TextView t = new TextView(this);
            t.setText("" + i);
            root.addView(t);
        }
    }

採用這種方法,如果有 幾千個數字要顯示,則要循環 幾千次,在手機裏創建幾千個TextView並渲染在手機屏幕上,這會佔用較大的內存空間,因爲手機屏幕能顯示的TextView可能只有幾個或十多個,這取決於 TextView的高寬。

設備的內存資源 是有限的。

ListView 和 ArrayAdapeter

LinearLayout + TextView 的會造成資源的浪費。

ListView 和 ArrayAdapeter 則不會,ArrayAdapeter是一個適配器 ,用於管理 視圖和 數據。

假如在手機屏幕中可以顯示 10 條 TextView ,而我們有 10000 個 數字需要顯示,用戶在滑動屏幕查看更多的數字時(上面的數字會移出屏幕,下面的數字會進入排列),適配器就會回收 移出數字的視圖資源,並將改視圖資源用於顯示新進入的數字。

代碼:

Numbers 的 xml 佈局文件:

<?xml version="1.0" encoding="utf-8"?>
    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".NumbersActivity" />

Numbers 頁面 的 onCreate 函數:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_numbers);
        // Create a array list of words
        ArrayList<String> words = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
   
   
            words.add("" + i);
        }
        
        // Create a ArrayAdapter
		ArrayAdapter<String> itemsAdapter =
                new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, words);
        // Get layout instance
        ListView listLayout = (ListView) findViewById(R.id.list);
        // Set adapter for the layout instance
        listLayout.setAdapter(itemsAdapter);
    }
  1. 首先創建了一個包含了 10000 個數字的 列表作爲數據來源
  2. 創建一個 ArrayAdapter 用於管理字符串數據(這裏是泛型),this 參數指定上下文,android.R.layout.simple_list_item_1 是Android中一個列表項佈局,words 指定數據來源
  3. findViewById(R.id.list) 獲取根視圖 ListView 的實例
  4. listLayout.setAdapter(itemsAdapter) 爲 根視圖綁定適配器

這樣適配器就可以管理 視圖視圖 和 數據來源了。

最後一步的 listLayout.setAdapter(itemsAdapter); 比較複雜,ListView 定義的 設置適配器方法爲 public void setAdapter(ListAdapter adapter) 要求接收一個 ListAdapter 對象,而最終轉入的卻是 ArrayAdapter 對象。

原因是:

ArrayAdapter 繼承自 抽象類 BaseAdapter ,BaseAdapter 實現了 ListAdapter 接口,所以 ArrayAdapter 也是 ListAdapter的實現。

運行效果,圖片大,只截部分,:

橫線是 android.R.layout.simple_list_item_1 的佈局樣式

在這裏插入圖片描述

內存性能分析器使用

在 Android Studio 的工具欄中 View --> Tool Windows --> Profiler ,即可打開 Profiler,它顯示一個應用內存使用量的實時圖表,讓您可以捕獲堆轉儲、強制執行垃圾回收以及跟蹤內存分配。

使用 Memory Profiler 對比 視圖回收中,兩種方法 在頁面顯示 1000 個數字的內存消耗情況:

在這裏插入圖片描述

LinearLouyout + TextView 的方式大概佔用了 18mb 的內存 資源,ListView + ArrayAdapter 的方式則消耗了 8mb 資源,只使用到了前者的一半不到。

如果有更多的內容需要顯示,兩者的 內存消耗會更加明顯;比如在微博 App 的首頁用戶可以一直往下刷,查看 幾千上萬條 動態 ,就使用到了 視圖回收的機制。

並且 LinearLouyout 要想在屏幕中滾動查看更多內容,需要配合 ScrollView 實現;而 ListView 默認支持在屏幕中滾動瀏覽更多的效果。

總結

視圖回收 機制在日常使用的 App 中十分常見,如微博,CSDN 等。

今天學的 內容差不多就這些了, 步驟不多,但涵蓋的概念和知識點不少,慢慢來。

參考

OnClickListener

<activity>

ListView | Android Developers

ArrayAdapter --> BaseAdapter --> ListAdapter

查看堆和內存分配

關於 ListView 和 ArrayAdapter 的 Codepath 教程。

關於 ListView 的 Google I/O 演講 Youtube 視頻。

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