1. 程式人生 > >《瞭解Android四大元件 》的補充

《瞭解Android四大元件 》的補充

Activity

View元件是所有UI控制元件、容器控制元件的基類,View元件就是Android應用中使用者實實在在看到的部分。但View元件需要放到容器元件中,或者使用Activity將它顯示出來。如果需要通過某個Activity把指定的View顯示出來,呼叫Activity的setContentView()方法即可。

  • 接受一個View物件作為引數
如: LinearLayout  layout = new LinearLayout(this);
setContentView(layout);
  • 接受一個佈局管理資源的ID作為引數
如: setContentView(R.layout.main);

其他知識,在《瞭解Android四大元件》中,有詳細完整的講解,並已經親測


Service

關於Activity和Service的選擇標準的一些事:
如果某個程式元件需要在執行時向用戶呈現某種介面,或者該程式需要與使用者互動,就需要使用Activity;否則就應該考慮使用Service

動手試試看

建立、配置Service
就如activity一樣,對於Service的開發也需要兩個步驟:

  • 定義一個繼承Service的子類
  • 在AndroidManifest.xml檔案中配置該Service

具體的需要被覆蓋的主要方法的詳解在《瞭解Android四大元件中》,在這裡直接上原始碼:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class FirstService extends Service
{
    // 必須實現的方法
    @Override
    public IBinder onBind(Intent arg0)
    {
        return null;
    }
    // Service被建立時回撥該方法
@Override public void onCreate() { super.onCreate(); System.out.println("Service is Created"); } // Service被啟動時回撥該方法 @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("Service is Started"); return START_STICKY; } // Service被關閉之前回調 @Override public void onDestroy() { super.onDestroy(); System.out.println("Service is Destroyed"); } }

在AndroidManifest.xml檔案中增加如下配置片段來配置Service:

        <service android:name=".FirstService">
        </service>
與配置Activity相似,配置Service時也可為<service.../>元素
配置<intent-filter.../>子元素,
用於說明該Service可被那些Intent啟動

啟動和停止Service

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    Button start, stop;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 獲取程式介面中的start、stop兩個按鈕
        start = (Button) findViewById(R.id.start);
        stop = (Button) findViewById(R.id.stop);
        // 建立啟動Service的Intent
        final Intent intent = new Intent(this , FirstService.class);
        start.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View arg0)
            {
                // 啟動指定Service的關鍵就是呼叫Context裡定義的startService
                startService(intent);
            }
        });
        stop.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View arg0)
            {
                // 停止指定Service關鍵就是呼叫Context裡定義的stopService
                stopService(intent);
            }
        });
    }
}

效果演示:(Logcat)

當按下“START”按鈕時:
這裡寫圖片描述

當按下”STOP”按鈕時:
這裡寫圖片描述

嘗試連按三下“START”
這裡寫圖片描述

我們可以發現,我們成功實現了FirstService中的被覆蓋的方法,並打印出想要的字,有一點值得注意:在效果圖三種,我們發現每次Service被啟動時都會回撥onStratCommond()方法,但多次啟動一個已有得Service元件將不會回撥onCreat()方法。

雖然這個Service幾乎什麼都沒幹,只是列印了幾行字而已,但是它是Service元件的框架,若想讓這個Service多做一些事,只需要在被覆蓋的onCreate() onStartCommand() onDestroy()的方法體中,實現相應的程式碼塊即可


BroadcastReceiver

啟動BroadcastReceiver的步驟

  1. 建立需要啟動的BroadcastReceiver的Intent
  2. 呼叫Context的sendBroadcast()或sendOrderedBroadcast()方法啟動指定的BroadcastReceiver

與OnXxxListener的區別
OnXxxListener只是程式級別的監聽器,這些監聽器執行在指定程式所在程序中,當程式退出時,OnXxxListener監聽器也就隨之關閉了。
但BroadcastReceiver是系統級別的監聽器,擁有自己的程序,只要存在與之匹配的Inten被廣播出來,BroadcastReceiver就會被激發。

如何指定BroadcastReceiver能匹配的Intent

  • 使用程式碼進行指定,呼叫BroadcastReceiver的Context的registerReceiver(BroadcastReceiver receiver,IntentFilter filter)方法指定。

  • 在AndroidManifest.xml檔案中配置。

**注意:**BroadcastReceiver的onReceive()方法不能再10秒內執行完成,Android會認為該程式無響應,故不要在此執行耗時的操作。(如果確實需要根據Broadcast來完成一項比較耗時的操作,則可以考慮通過Intent啟動一個Service來完成該操作)

動手試試傳送廣播

首先在activity_main.xml中建立一個用於傳送的按鈕(基本操作,程式碼就不放上來了)。

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    Button send;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 獲取程式介面中的按鈕
        send = (Button) findViewById(R.id.send);
        send.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
            /*
            *建立一個Intent物件,並使用該Intent物件對外發送一條廣播
            */
                // 建立Intent物件
                Intent intent = new Intent();
                // 設定Intent的Action屬性
                intent.setAction("org.crazyit.action.CRAZY_BROADCAST");
                intent.putExtra("msg", "簡單的訊息");
                // 傳送廣播
                sendBroadcast(intent);
            }
        });
    }
}

當符合該MyReceiver的廣播出現時,該MyReceiver的onReceiver()方法將會被出發,從而在該方法中顯示廣播所攜帶的資訊。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Toast.makeText(context,
            "接收到的Intent的Action為:" + intent.getAction()
            + "\n訊息內容是:" + intent.getStringExtra("msg")
            , Toast.LENGTH_LONG).show();
    }
}

因為上面廣播所用的Intent的Action為org.crazyit.action.CRAZY_BROADCAST,這就需要配置上面的BroadcastReceiver應監聽Action為該字串的Intent,在AndroidMainifest.xml檔案中增加程式碼塊

        <receiver android:name=".MyReceiver">
            <intent-filter>
                <!-- 指定該BroadcastReceiver所響應的Intent的Action -->
                <action android:name="org.crazyit.action.CRAZY_BROADCAST" />
            </intent-filter>
        </receiver>

點選“send”Button按鈕效果圖:
這裡寫圖片描述

這裡演示的是使用者傳送的廣播,需要明白BroadcastReceiver還有一個重要的用途:接受系統廣播訊息。
其他這裡未寫到的內容見《瞭解Android四大元件》一文。


ContentProvider

在《瘋狂Android講義》中,有如下類比幫助我們理解ContentProvider、ContentResolver兩個核心API的作業。

把ContentProvider當做Android系統內部的“網站”,這個網站以固定的Uri對外提供服務;而ContentResolver則可當成Android系統內部的HttpClient,它可以向指定Uri傳送“請求”(實際上是呼叫ContentResolver的方法),這種請求最後委託給ContentProvider處理,從而實現對“網站”(即ContentProvider)內部資料進行操作。

這裡寫圖片描述

ContentProvider只有一個onCreate()生命週期方法——當其他應用通過ContentResolver第一次訪問該ContentProvider時,onCreate()方法將會被回撥,onCreate()方法只會被呼叫一次;ContentProvider提供的query(),insert(),update()和delete()方法則由其他應用通過ContentResolver呼叫

那如何開發一個ContentProvider呢?

  1. 定義自己的ContentProvider類,該類需要繼承Android提供的ContentProvider基類。
  2. 在Androidmanifest.xml檔案中註冊這個ContentProvider,註冊時也需要為它繫結一個Uri