日報2015/10/15(極客學院安卓視頻學習)

Android 中 Context 的理解及使用

Context實際上用來管理訪問全局資源

getContext().getResources().getXXX

這行代碼就可以訪問到全局的字符串、圖片等資源

例如給一個TextView設置內容:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = new TextView(this);
        //訪問到全局資源:字符串hello_world
        textView.setText(R.string.hello_world);
        setContentView(textView);
    }

上面這個TextView**引用**了this,也就是MainActivity這個context,所以能訪問到全局資源,比如R.string.hello_world。

看一下源碼

    @android.view.RemotableViewMethod
    public final void setText(@StringRes int resid) {
        setText(getContext().getResources().getText(resid));
    }

可以看到這句代碼可以訪問資源,而由於TextView在構造的時候傳了this進去,getContext()返回的就是當前的MainActivity。

又例如ImageView也可以這麼做

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = new ImageView(this);
        //訪問ic_launcher這個圖片資源
        imageView.setImageResource(R.mipmap.ic_launcher);
        setContentView(imageView);
    }

這裏寫圖片描述


從這裏開始就是收費課程了,30軟一個月還蠻便宜的其實

Application 的用途

Application纔是真正的全局上下文對象,可以進行組件之間信息共享的橋樑。

在項目裏指定一個繼承自Application的java類 app

併爲兩個Activity都指定爲程序入口
這裏寫圖片描述

在Main1裏通過輸入文本對app裏面的成員變量dataText進行修改,然後測試Main2中是否能讀取到修改後的dataText

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.shareText);
        textView.setText(((App) getApplicationContext()).getTextData());
        editText = (EditText) findViewById(R.id.editText);
        button = (Button) findViewById(R.id.btnSave);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((App) getApplicationContext()).setTextData(editText.getText().toString());
            }
        });
    }

運行後發現報錯了

java.lang.ClassCastException: android.app.Application cannot be cast to com.jackie.coursecontext.App

找了一下原因,是AndroidManifest.xml裏面忘記讓當前的Application指向我們自定義的app了

修改一下

<application
        android:name=".App"
        ...

重新運行,Main2中顯示的就是之前輸入的字符串了


Application 生命週期

重寫一下上面App類繼承自Application的一些方法

onCreate()//創建時執行
onTerminate()//終止時執行
onTrimMemory(int level)
onLowMemory()
onConfigurationChanged(Configuration newConfig)//配置變化時執行

分別給app,Main1,Main2 的週期添加一些Log

10-15 06:36:14.072  24348-24348/com.jackie.coursecontext V/jackie﹕ App Created
10-15 06:36:14.088  24348-24348/com.jackie.coursecontext V/jackie﹕ Main1 Created
10-15 06:42:02.764  26781-26781/com.jackie.coursecontext V/jackie﹕ App Created
10-15 06:42:02.768  26781-26781/com.jackie.coursecontext V/jackie﹕ Main2 Created

可以看到最先執行的是Application的onCreate() 也就是說一些初始化操作放在Application裏面是很好的


認識 Android Service

程序有的時候不需要與用戶交互,只需要在後臺進行一些動作,這時候就可以用service了

啓動、停止service的時候無論使用1個intent還是2個,操作的都是同一個service。

startService(new Intent(MainActivity.this, MyService.class));
stopService(new Intent(MainActivity.this,MyService.class));

在安卓機上面設置-Apps裏面可以看到正在運行的進程,可以看到一些service。

爲了便於觀察,在自定義service時,重寫一下

onStartCommand(Intent intent, int flags, int startId)

這個方法是在service被啓動時執行

在裏面啓動一個線程,循環執行一個正在運行的語句,以便觀察

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    Log.v("jackie","服務正在運行...");
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
10-15 08:50:01.110    2093-3004/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-15 08:50:01.800    2093-2557/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-15 08:50:02.120    2093-3004/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-15 08:50:02.810    2093-2557/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-15 08:50:03.131    2093-3004/com.jackie.courseservice V/jackie﹕ 服務正在運行...

即使此退出Activity,service也不會停止。

由於這裏按鈕較多,如果每一個按鈕都去寫一個OnClickListener() 那麼會顯得很冗餘。可以讓這個MainActivity**實現OnClickListener接口(非常重要)**,然後重寫當前Activity的OnClick(View v) 通過View的id來區分功能,然後按鈕只要綁定當前Activity就行了。

        findViewById(R.id.btnStart).setOnClickListener(this);
        findViewById(R.id.btnStop).setOnClickListener(this);
        findViewById(R.id.btnBind).setOnClickListener(this);
        findViewById(R.id.btnUnBind).setOnClickListener(this);
        ...
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btnStart:
                Log.v("jackie", "開始服務");
                startService(new Intent(MainActivity.this, MyService.class));
                break;
            case R.id.btnStop:
                Log.v("jackie","停止服務");
                stopService(new Intent(MainActivity.this, MyService.class));
                break;
            case R.id.btnBind:
                Log.v("jackie", "綁定服務");
                bindService(new Intent(MainActivity.this, MyService.class), this, BIND_AUTO_CREATE);
                break;
            case R.id.btnUnBind:
                Log.v("jackie", "解綁服務");
                unbindService(this);
                break;

        }
    }

如果直接就這樣啓動的話:會報錯

java.lang.RuntimeException: Unable to bind to service

因爲onBind() 方法還沒有進行重寫

    @Override
    public IBinder onBind(Intent intent) {
        return new Binder();

    }

點擊綁定服務

10-15 09:20:45.091  15889-15889/com.jackie.courseservice V/jackie﹕ 綁定服務
10-15 09:20:45.131  15889-15889/com.jackie.courseservice V/jackie﹕ Service Connected

Service生命週期

這裏寫圖片描述

啓動並且綁定服務,如果直接停止服務的話,可以看到,Service並沒有destroyed

10-15 09:29:32.380  18152-18152/com.jackie.courseservice V/jackie﹕ 開始服務
10-15 09:29:32.408  18152-18152/com.jackie.courseservice V/jackie﹕ Service created
10-15 09:29:34.393  18152-18152/com.jackie.courseservice V/jackie﹕ 綁定服務
10-15 09:29:34.407  18152-18152/com.jackie.courseservice V/jackie﹕ Service Connected
    --------- beginning of system
10-15 09:30:06.144  18152-18152/com.jackie.courseservice V/jackie﹕ 停止服務

必須解綁,纔會destroyed

10-15 09:31:32.793  18152-18152/com.jackie.courseservice V/jackie﹕ 解綁服務
10-15 09:31:32.801  18152-18152/com.jackie.courseservice V/jackie﹕ Service destroyed

如果在已經綁定服務的情況下,直接退出Activity,會報異常

10-15 09:32:52.379  18152-18152/com.jackie.courseservice E/ActivityThread﹕ Activity com.jackie.courseservice.MainActivity has leaked ServiceConnection com.jackie.courseservice.MainActivity@1c2f7e9 that was originally bound here
    android.app.ServiceConnectionLeaked: Activity com.jackie.courseservice.MainActivity has leaked ServiceConnection com.jackie.courseservice.MainActivity@1c2f7e9 that was originally bound here

同時,Service會destroy

10-15 09:32:52.384  18152-18152/com.jackie.courseservice V/jackie﹕ Service destroyed

重寫一下onStartCommand(Intent intent, int flags, int startId) ,添加一句Log

點擊啓動服務按鈕:

10-15 09:37:35.279  22880-22880/com.jackie.courseservice V/jackie﹕ 開始服務
10-15 09:37:35.298  22880-22880/com.jackie.courseservice V/jackie﹕ Service created
10-15 09:37:35.298  22880-22880/com.jackie.courseservice V/jackie﹕ Command started

如果重複點擊啓動服務按鈕,可以看到LogCat

10-15 09:37:35.298  22880-22880/com.jackie.courseservice V/jackie﹕ Command started
10-15 09:38:41.231  22880-22880/com.jackie.courseservice V/jackie﹕ 開始服務
10-15 09:38:41.242  22880-22880/com.jackie.courseservice V/jackie﹕ Command started
10-15 09:38:41.650  22880-22880/com.jackie.courseservice V/jackie﹕ 開始服務
10-15 09:38:41.653  22880-22880/com.jackie.courseservice V/jackie﹕ Command started
10-15 09:38:42.061  22880-22880/com.jackie.courseservice V/jackie﹕ 開始服務
10-15 09:38:42.079  22880-22880/com.jackie.courseservice V/jackie﹕ Command started

可見無論怎麼點擊,onCreate() 都只執行一次,而onStartCommand() 則每點擊一次就執行一次。

給MyService添加成員變量private boolean isRunning = false;
並且onCreate()isRunning = true;onDestroy()isRunning = false;

啓動/停止服務;

10-15 10:01:37.030      711-711/com.jackie.courseservice V/jackie﹕ 開始服務
10-15 10:01:37.034      711-711/com.jackie.courseservice V/jackie﹕ Service created
10-15 10:01:37.034      711-711/com.jackie.courseservice V/jackie﹕ Command started
10-15 10:01:37.044      711-865/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-15 10:01:39.055      711-865/com.jackie.courseservice V/jackie﹕ 服務正在運行...
10-15 10:01:40.218      711-711/com.jackie.courseservice V/jackie﹕ 停止服務
10-15 10:01:40.223      711-711/com.jackie.courseservice V/jackie﹕ Service destroyed
發佈了30 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章